Node.js の 16系 を試そうとしたら gulp-sass, node-sass 周りでエラーが発生したので対処をまとめておきます。
経緯
まず前提として
- Dart Sass で
/
を使った徐算が非推奨となった (代わりにmath.div
を使えとのこと) - 上述現象を回避するため、
sass
のバージョンを1.32.12
で固定していた
という事情があります。
現象
この状態で Node.js のバージョンを 16系 に切り替えて yarn
。
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);
^~~~~~~~~~~
/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);
^~~~~~~~~~~
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);
^~~~~~~~~~~
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);
^~~~~~~
/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);
^~~~~~~
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);
^~~~~~~~~~~~
../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);
^~~~~~~~~~~~
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)
^~~~~~~~~~~~~
../src/binding.cpp:358:1: note: in expansion of macro 'NODE_MODULE'
NODE_MODULE(binding, RegisterModule);
^~~~~~~~~~~
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
……滅茶苦茶怒られました (Docker内のLinux環境)。
ちなみに Windows環境だと yarn
時にはエラーにはなりませんが、 Gulpタスク を走らせた際に同様のエラーメッセージが表示されます。
対処1 (sass, gulp-sass のバージョンを上げる)
そこでまずは sass
のバージョンを上げます。
ちなみに、 1.35.0
以降 では quietDeps: true
のフラグを追加することで、冒頭の警告を非表示にできるようになったとのことなので、そもそもの問題は回避できるはずです。
"devDependencies": {
// 略
"gulp-sass": "^4.1.0",
"sass": "1.35.1", // 1.32.12 からアップデート
"fibers": "^5.0.0",
"gulp-autoprefixer": "^7.0.1",
// 略
}
これで yarn
してみましたが、ダメ。
ふと gulp-sass
を見てみると、いつの間にか 5.0.0
がリリースされているではありませんか。
"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",
// 略
}
そこで、 gulp-sass
も上げます。これで yarn
すると正常に完了。
安心して Gulpタスク を走らせると……
../src/coroutine.cc:134: void* find_thread_id_key(void*): Assertion `thread_id_key != 0x7777' failed.
…別のエラーで怒られました。
対処2 (fibers を削除)
検索すると上述のエラーは fibers
が Node.js 16系 に対応していないために発生している模様。
そのため、 fibers
を削除します。
"devDependencies": {
// 略
"gulp-sass": "^5.0.0", // 4.1.0 からアップデート
"sass": "1.35.1", // 1.32.12 からアップデート
"gulp-autoprefixer": "^7.0.1",
// 略
}
併せてタスクも書き換えます。
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))
// 略
fibers
関係を削除。
これで yarn
し直してタスクを再実行。
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'));
……別のエラーが発生しました。どうやら gulp-sass
の Scssトランスパイラ の指定方法が変わったようです。
対処3 (gulp-sass のScssトランスパイラ指定方法を変更)
const sass = require('gulp-sass')(require('sass'));
//const Fiber = require('fibers');
// 略
.pipe(sass({
// fiber: Fiber,
outputStyle: 'compressed',
quietDeps: true // 警告回避のために追加
}).on('error', sass.logError))
// 略
これでようやくタスクが正常に走るようになりました。
参考
- Dart Sass の警告回避:
- fibers: node.js – (thread_id_key != 0x7777), function find_thread_id_key, file ../src/coroutine.cc, line 134 – Stack Overflow
- gulp-sass: gulp-sass – npm