tag:crieit.net,2005:https://crieit.net/tags/gulp-sass/feed
「gulp-sass」の記事 - Crieit
Crieitでタグ「gulp-sass」に投稿された最近の記事
2021-07-05T20:32:23+09:00
https://crieit.net/tags/gulp-sass/feed
tag:crieit.net,2005:PublicArticle/17485
2021-07-05T20:32:23+09:00
2021-07-05T20:32:23+09:00
https://crieit.net/posts/node-sass-adjust-node16-20210705
gulp-sass を Node.js v16 環境に合わせて調整する
<p>Node.js の 16系 を試そうとしたら gulp-sass, node-sass 周りでエラーが発生したので対処をまとめておきます。</p>
<h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2>
<p>まず前提として</p>
<ul>
<li>Dart Sass で <code>/</code> を使った徐算が非推奨となった (代わりに <code>math.div</code> を使えとのこと)
<ul>
<li>参考: <a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2021/06/07/dart-sass-warning-slash-as-division/">Dart Sass で DEPRECATION WARNING: Using / for division is deprecated and will be removed in Dart Sass 2.0.0. の警告が表示される - Ewig Leere(Lab2)</a></li>
</ul></li>
<li>上述現象を回避するため、 <code>sass</code> のバージョンを <code>1.32.12</code> で固定していた</li>
</ul>
<p>という事情があります。</p>
<h2 id="現象"><a href="#%E7%8F%BE%E8%B1%A1">現象</a></h2>
<p>この状態で Node.js のバージョンを 16系 に切り替えて <code>yarn</code> 。</p>
<pre><code class="bash">error /home/node/app/node_modules/node-sass: Command failed.
Exit code: 1
Command: node scripts/build.js
Arguments:
Directory: /home/node/app/node_modules/node-sass
Output:
Building: /usr/local/bin/node /home/node/app/node_modules/node-gyp/bin/node-gyp.js rebuild --verbose --libsass_ext= --libsass_cflags= --libsass_ldflags= --libsass_library=
# 略
In file included from /home/node/.node-gyp/16.3.0/include/node/v8.h:30,
from /home/node/.node-gyp/16.3.0/include/node/node.h:63,
from ../../nan/nan.h:56,
from ../src/binding.cpp:1:
/home/node/.node-gyp/16.3.0/include/node/v8-internal.h: In function 'void v8::internal::PerformCastCheck(T*)':
/home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:38: error: 'remove_cv_t' is not a member of 'std'
!std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
^~~~~~~~~<del>
/home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:38: note: suggested alternative: 'remove_cv'
!std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
^</del>~~~~~~<del>
remove_cv
/home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:38: error: 'remove_cv_t' is not a member of 'std'
/home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:38: note: suggested alternative: 'remove_cv'
!std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
^</del>~~~~~~<del>
remove_cv
/home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:50: error: template argument 2 is invalid
!std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
^
/home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:63: error: '::Perform' has not been declared
!std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
^</del>~~<del>
/home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:63: note: suggested alternative: 'herror'
!std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
^</del>~~<del>
herror
../src/binding.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE render(Nan::NAN_METHOD_ARGS_TYPE)':
../src/binding.cpp:284:98: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback);
^</del>~~~~~~~<del>
../src/binding.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE render_file(Nan::NAN_METHOD_ARGS_TYPE)':
../src/binding.cpp:320:98: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback);
^</del>~~~~~~~<del>
In file included from ../../nan/nan.h:56,
from ../src/binding.cpp:1:
../src/binding.cpp: At global scope:
/home/node/.node-gyp/16.3.0/include/node/node.h:806:43: warning: cast between incompatible function types from 'void (*)(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE)' {aka 'void (*)(v8::Local<v8::Object>)'} to 'node::addon_register_func' {aka 'void (*)(v8::Local<v8::Object>, v8::Local<v8::Value>, void*)'} [-Wcast-function-type]
(node::addon_register_func) (regfunc), \
^
/home/node/.node-gyp/16.3.0/include/node/node.h:840:3: note: in expansion of macro 'NODE_MODULE_X'
NODE_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage)
^</del>~~~~~~~~<del>
../src/binding.cpp:358:1: note: in expansion of macro 'NODE_MODULE'
NODE_MODULE(binding, RegisterModule);
^</del>~~~~~~~~
make: *** [binding.target.mk:133: Release/obj.target/binding/src/binding.o] Error 1
make: Leaving directory '/home/node/app/node_modules/node-sass/build'
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/home/node/app/node_modules/node-gyp/lib/build.js:262:23)
gyp ERR! stack at ChildProcess.emit (node:events:394:28)
gyp ERR! stack at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12)
gyp ERR! System Linux 5.10.25-linuxkit
gyp ERR! command "/usr/local/bin/node" "/home/node/app/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd /home/node/app/node_modules/node-sass
gyp ERR! node -v v16.3.0
</code></pre>
<p>……滅茶苦茶怒られました (Docker内のLinux環境)。</p>
<p>ちなみに Windows環境だと <code>yarn</code> 時にはエラーにはなりませんが、 Gulpタスク を走らせた際に同様のエラーメッセージが表示されます。</p>
<p><a href="https://crieit.now.sh/upload_images/68677d73f1123631b69e1a1fa1061c7b60e2edbdef2fa.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/68677d73f1123631b69e1a1fa1061c7b60e2edbdef2fa.jpg?mw=700" alt="Windows環境でのエラーメッセージ" /></a></p>
<h2 id="対処1 (sass, gulp-sass のバージョンを上げる)"><a href="#%E5%AF%BE%E5%87%A61+%28sass%2C+gulp-sass+%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E4%B8%8A%E3%81%92%E3%82%8B%29">対処1 (sass, gulp-sass のバージョンを上げる)</a></h2>
<p>そこでまずは <code>sass</code> のバージョンを上げます。</p>
<p>ちなみに、 <code>1.35.0</code>以降 では <code>quietDeps: true</code> のフラグを追加することで、冒頭の警告を非表示にできるようになったとのことなので、そもそもの問題は回避できるはずです。</p>
<pre><code class="json"> "devDependencies": {
// 略
"gulp-sass": "^4.1.0",
"sass": "1.35.1", // 1.32.12 からアップデート
"fibers": "^5.0.0",
"gulp-autoprefixer": "^7.0.1",
// 略
}
</code></pre>
<p>これで <code>yarn</code> してみましたが、ダメ。</p>
<p>ふと <code>gulp-sass</code> を見てみると、いつの間にか <code>5.0.0</code> がリリースされているではありませんか。</p>
<pre><code class="json"> "devDependencies": {
// 略
"gulp-sass": "^5.0.0", // 4.1.0 からアップデート
"sass": "1.35.1", // 1.32.12 からアップデート
"fibers": "^5.0.0",
"gulp-autoprefixer": "^7.0.1",
// 略
}
</code></pre>
<p>そこで、 <code>gulp-sass</code> も上げます。これで <code>yarn</code> すると正常に完了。</p>
<p>安心して Gulpタスク を走らせると……</p>
<pre><code class="bash">../src/coroutine.cc:134: void* find_thread_id_key(void*): Assertion `thread_id_key != 0x7777' failed.
</code></pre>
<p>…別のエラーで怒られました。</p>
<h2 id="対処2 (fibers を削除)"><a href="#%E5%AF%BE%E5%87%A62+%28fibers+%E3%82%92%E5%89%8A%E9%99%A4%29">対処2 (fibers を削除)</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/67330252/thread-id-key-0x7777-function-find-thread-id-key-file-src-coroutine-cc">node.js - (thread_id_key != 0x7777), function find_thread_id_key, file ../src/coroutine.cc, line 134 - Stack Overflow</a></li>
</ul>
<p>検索すると上述のエラーは <code>fibers</code> が Node.js 16系 に対応していないために発生している模様。</p>
<p>そのため、 <code>fibers</code> を削除します。</p>
<pre><code class="json"> "devDependencies": {
// 略
"gulp-sass": "^5.0.0", // 4.1.0 からアップデート
"sass": "1.35.1", // 1.32.12 からアップデート
"gulp-autoprefixer": "^7.0.1",
// 略
}
</code></pre>
<p>併せてタスクも書き換えます。</p>
<pre><code class="javascript">const sass = require('gulp-sass');
sass.compiler = require('sass');
//const Fiber = require('fibers');
// 略
.pipe(sass({
// fiber: Fiber,
outputStyle: 'compressed',
quietDeps: true // 警告回避のために追加
}).on('error', sass.logError))
// 略
</code></pre>
<p><code>fibers</code> 関係を削除。</p>
<p>これで <code>yarn</code> し直してタスクを再実行。</p>
<pre><code class="bash">Error in plugin "gulp-sass"
Message:
gulp-sass 5 does not have a default Sass compiler; please set one yourself.
Both the `sass` and `node-sass` packages are permitted.
For example, in your gulpfile:
var sass = require('gulp-sass')(require('sass'));
</code></pre>
<p>……別のエラーが発生しました。どうやら <code>gulp-sass</code> の Scssトランスパイラ の指定方法が変わったようです。</p>
<h2 id="対処3 (gulp-sass のScssトランスパイラ指定方法を変更)"><a href="#%E5%AF%BE%E5%87%A63+%28gulp-sass+%E3%81%AEScss%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B9%E3%83%91%E3%82%A4%E3%83%A9%E6%8C%87%E5%AE%9A%E6%96%B9%E6%B3%95%E3%82%92%E5%A4%89%E6%9B%B4%29">対処3 (gulp-sass のScssトランスパイラ指定方法を変更)</a></h2>
<pre><code class="javascript">const sass = require('gulp-sass')(require('sass'));
//const Fiber = require('fibers');
// 略
.pipe(sass({
// fiber: Fiber,
outputStyle: 'compressed',
quietDeps: true // 警告回避のために追加
}).on('error', sass.logError))
// 略
</code></pre>
<p>これでようやくタスクが正常に走るようになりました。</p>
<h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2>
<ul>
<li>Dart Sass の警告回避:
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://sass-lang.com/documentation/js-api#quietdeps">Sass: JavaScript API</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/twbs/bootstrap/issues/34051">Sass deprecation warning: Using `/` for division is deprecated · Issue #34051 · twbs/bootstrap · GitHub</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/sass/dart-sass/issues/1333">support quietDeps flag · Issue #1333 · sass/dart-sass · GitHub</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/sass/dart-sass/issues/672">Add a --quiet-upstream flag · Issue #672 · sass/dart-sass · GitHub</a></li>
</ul></li>
<li>fibers: <a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/67330252/thread-id-key-0x7777-function-find-thread-id-key-file-src-coroutine-cc">node.js - (thread_id_key != 0x7777), function find_thread_id_key, file ../src/coroutine.cc, line 134 - Stack Overflow</a></li>
<li>gulp-sass: <a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/gulp-sass">gulp-sass - npm</a></li>
</ul>
arm-band
tag:crieit.net,2005:PublicArticle/16652
2021-01-26T23:55:22+09:00
2021-01-26T23:55:22+09:00
https://crieit.net/posts/gulp-sass-pseudo-dynamic-import-scss-20210120
gulp-sass から Scss を疑似的な動的読み込みを行う
<h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2>
<p>Scss で <code>@import</code>, <code>@use</code>, <code>@forward</code> のような他のファイルを読み込む機能は、 @ディレクティブ 内では使用できないません。そのため、例えば以下のようなことができません。</p>
<pre><code class="scss">$flag: true;
@if ($flag) {
@use "parts1.scss";
}
</code></pre>
<p>あるフラグ変数(ここでは <code>$flag</code> ですが、実際はファイル中ではなく Gulp タスク内で管理)が <code>true</code> のときのみ <code>parts1.scss</code> を読み込む。</p>
<pre><code class="scss">$flag: true;
@if ($flag) {
@use "parts1.scss";
}
@else {
@use "parts2.scss";
}
</code></pre>
<p>あるいは、フラグ変数の値によって読み込む Scss ファイルを切り替える。</p>
<p>この部分について、どうにかできないか(本当にやりたいのは最初の例ですが、代替案として2つ目の例でブランクの <code>parts2.scss</code> をダミーとして用意する方法を考える)、と。</p>
<h2 id="対処"><a href="#%E5%AF%BE%E5%87%A6">対処</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/63803090/sass-dynamic-import-based-on-environment">css - Sass dynamic import based on environment - Stack Overflow</a></li>
</ul>
<p>色々検索した結果、 <code>gulp-sass</code> の <code>includePaths</code> オプションを使えばそれらしいことができそうだ、ということが分かりました。</p>
<p>今回はたまたま自分も <code>gulp-sass</code> を使用している前提で、しかも Scss 本体の変数ではなく Gulp タスク内で管理しているフラグによって、というのが希望だったのでこの形はぴったりでした (この方法でなければ、上記スレの上の方にあるように、フラグをいったん Scss ファイルに変数として出力し、それを読み込むことで伝播させようと考えていました)。</p>
<pre><code class="javascript">const { src, dest } = require('gulp');
const plumber = require('gulp-plumber');
const notify = require('gulp-notify');
const sass = require('gulp-sass');
sass.compiler = require('sass');
const Fiber = require('fibers');
const autoprefixer = require('gulp-autoprefixer');
// dynamic import test
const flag = true;
// scssコンパイルタスク
const scss = () => {
let opt = {
fiber: Fiber,
outputStyle: 'compressed'
};
// dynamic import test
if (flag) {
opt.includePaths = [
`src/scss/parts/enable`
]
}
else {
opt.includePaths = [
`src/scss/parts/disable`
]
}
return src('src/scss/**/*.scss')
.pipe(plumber({
errorHandler: notify.onError({
message: 'Error: <%= error.message %>',
title: 'scss'
})
}))
.pipe(sass(opt).on('error', sass.logError))
.pipe(autoprefixer({
cascade: false
}))
.pipe(dest('dist/css'));
};
module.exports = scss;
</code></pre>
<p>Scss のコンパイルタスクはこのような感じで。</p>
<pre><code>src/
└ scss/
├ .scssファイル やディレクトリ
├ import/
│ └ _index.scss
│
└ parts/
├ disable/
│ └ parts_hoge.scss
└ enable/
└ parts_hoge.scss
</code></pre>
<p>このようなディレクトリ構造で、 <code>src/scss/import/_index.scss</code> から <code>src/scss/parts</code> の中の<code>enable</code> または <code>disable</code> のどちらかの <code>parts_hoge.scss</code> を読み込む、とした場合。</p>
<pre><code class="scss">// dynamic import test
@use "parts_hoge";
</code></pre>
<p><code>src/scss/import/_index.scss</code> の記述はこれだけですが、 Scss のコンパイルタスクに記述されている変数 <code>flag</code> によって読み込む元のディレクトリの候補が <code>src/scss/parts/enable</code> または <code>src/scss/parts/disable</code> のどちらかに切り替わる、ということです。</p>
<p>あとは <code>src/scss/parts/disable/parts_hoge.scss</code> は中身のないブランクのファイルにしておけば、 <code>flag</code> が <code>true</code> の場合のみ css が当たる、ということになります。</p>
<p>出力される css の切り分けはできたので、とりあえずはこの方法でしょうかね。</p>
<h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/63803090/sass-dynamic-import-based-on-environment">css - Sass dynamic import based on environment - Stack Overflow</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/sass">sass - npm</a></li>
<li><a target="_blank" rel="nofollow noopener" href="https://github.com/sass/node-sass#includepaths">sass/node-sass: Node.js bindings to libsass</a></li>
</ul>
arm-band