Maglevを無効化したらNode.js v24でもsvg2ttfが実行できる
問題が無い環境
Docker for Macで実行しているnode 22のコンテナから、Mac側にあるソースコードをマウントしている場合
Mac側にインストールしたnode 24を実行する場合
問題が発生する環境
Docker for Macで実行しているnode 24のコンテナから、Mac側にあるソースコードをマウントしている場合
以下、この環境でのsvg2ttfの実行方法を説明する
Node.js v24ではsvg2ttfの呼び出し方を工夫しなければならない
こうする
code:diff
diff --git a/scripts/build-assets/iconfont-woff2.sh b/scripts/build-assets/iconfont-woff2.sh
index 9b54b8047..3cbcbb186 100644
--- a/scripts/build-assets/iconfont-woff2.sh
+++ b/scripts/build-assets/iconfont-woff2.sh
@@ -2,7 +2,7 @@ set -eu
readonly BASE_PATH="public/assets/fonts/AppIcons"
-svg2ttf ${BASE_PATH}.svg ${BASE_PATH}.ttf
+node --no-maglev ./node_modules/.bin/svg2ttf ${BASE_PATH}.svg ${BASE_PATH}.ttf
echo "created: ${BASE_PATH}.ttf"
cat ${BASE_PATH}.ttf | ttf2woff2 > ${BASE_PATH}.woff2
--no-maglevはNODE_OPTIONSに付けられない
$ NODE_OPTIONS=--no-maglev svg2ttf ${BASE_PATH}.svg ${BASE_PATH}.ttf
実行するとnode: --no-maglev is not allowed in NODE_OPTIONSというエラーで止まる
どういう時に必要なのか
kamonの中にある全てのSVGをwebフォント化する時に
まずsvgicons2svgfontで1つのSVGにまとめて
それをsvg2ttfでttfにする
これがNode 24だとJavaScript heap out of memoryでクラッシュする
ttfをttf2woff2でwebフォント(woff形式)にする
SVGファイルの数が少なければ問題ない
170個ぐらいまとめて処理するとクラッシュする
svg2ttfのクラッシュの様子
https://gyazo.com/e4fc39f3d8d4590f007ffcb1a67fc588
code:log
53:0x6de2000 386584 ms: Scavenge (interleaved) 2001.9 (2018.9) -> 1989.4 (2052.6) MB, pooled: 0 MB, 8.44 / 0.00 ms (average mu =
0.225, current mu = 0.173) allocation failure;
53:0x6de2000 387209 ms: Mark-Compact (reduce) 1989.6 (2052.6) -> 1989.5 (1991.6) MB, pooled: 0 MB, 552.48 / 0.00 ms (+ 0.7 ms in
2 steps since start of marking, biggest step 0.7 ms, walltime since start of marking 556 ms) (average mu = 0.235, current
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 0xf1f241 node::OOMErrorHandler(char const*, v8::OOMDetails const&) node
2: 0x13563a0 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) node
3: 0x135648f v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) node
4: 0x15ecad5 node
5: 0x15ecb02 node
6: 0x15ecdfa v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector, v8::base::TimeTicks) node 7: 0x15fd31a node 8: 0x16016c0 node 9: 0x2091c61 node Aborted
発見の経緯
Node.js v22の最近のバージョンで、↑のクラッシュがいつのまにか解決していた
svg2ttfとsvgicons2svgfontの両方で起きていたが、どちらも解決していた
Node.js v24ではsvgicons2svgfontは動くようになったが、まだsvg2ttfはクラッシュする
原因を知りたいshokai.icon
node 22でだけ動くという状況が、非常に臭い
node 22と24の両方で動くなら、きちんとbug修正がされたのだと想像できる
22では動くのに24では動かないというのは、何か暫定的な対処がされたのではないか?
それだと、node 22でも再発するかもしれない
どのバージョンでビルド通るようになったのか?
ビルドできる
22.17.1
22.10.0
22.9.0
JavaScript heap out of memoryが出る
22.8.0
22.5.1
22.9.0で修正された
22.9.0ではビルドできるが、22.8.0ではビルドできない
22.8.1などのpatch versionは無い
22.9.0のどの変更で修正されたのか?
https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V22.md#2024-09-17-version-2290-current-rafaelgss
Disable V8 Maglev
https://github.com/nodejs/node/pull/54384
これが怪しいshokai.icon
で、--no-maglev付けたらNode 24でもクラッシュしなかったので正解
Maglevは、V8の多段階コンパイルに新たに追加された3段階目である
V8の多段階コンパイル戦略 (2025年調べ)でまとめた
運用の知見
Node.js更新によって特定のツールだけ動かなくなった場合、多段階コンパイラを1つずつ無効化してみる