gulp-sass を Node.js v16 環境に合わせて調整する

Node.js の 16系 を試そうとしたら gulp-sass, node-sass 周りでエラーが発生したので対処をまとめておきます。

経緯

まず前提として

という事情があります。

現象

この状態で 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タスク を走らせた際に同様のエラーメッセージが表示されます。

Windows環境でのエラーメッセージ
Windows環境でのエラーメッセージ

対処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))

// 略

これでようやくタスクが正常に走るようになりました。

参考

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。