Rails5.1のbin/webpacker-dev-serverでJavaScript heap out of memoryが起きた時の対処方

概要

Rails5.1 のbin/webpacker-dev-serverでOOM起きた時の対処法を記載します。
 フロント:React(or Vue or Angular)
 サーバー:Rails
で開発をして、そこそこ規模が大きくなると誰でも発生するかと思います。
これが起きると、開発効率+心的ストレス面でかなり問題になるので、まだなっていないけど、同環境の方はストックしてみてください。

事象

Rails 5.1 でReactやVueを実行するためのWebpackerが正式に対応されました。
Rails5.1から追加されると噂のWebpackerを使ってReact.jsを動かす。

開発時にReactの記法で書かれたJSXファイルを即時コンパイルし、ブラウザ描写するには
以下のコマンドを実行することでNodeがサーバーを起動し、結果を確認しながらコーディングすることができます。

terminal
$ bin/webpacker-dev-server

プロジェクトが小さいうちはなんの問題も無いのですが、大きくなるにつれ、コンパイル時に利用するメモリ量が増大していきます。
そこで制限値を超えたメモリ量(デフォルトは1.4G)を使用するとJavaScript heap out of memoryが発生します。

JavaScript heap out of memoryが起きると、Nodeサーバーが停止し、即時コンパイルができなくなります。
エラー内容は以下の通りです。

webpack: Compiling...

<--- Last few GCs --->

[39191:0x102801c00]   128125 ms: Mark-sweep 1401.3 (1456.1) -> 1401.3 (1456.1) MB, 469.1 / 0.0 ms  allocation failure GC in old space requested
[39191:0x102801c00]   128573 ms: Mark-sweep 1401.3 (1456.1) -> 1401.3 (1427.6) MB, 448.4 / 0.0 ms  last resort 
[39191:0x102801c00]   129048 ms: Mark-sweep 1401.3 (1427.6) -> 1401.3 (1427.1) MB, 474.8 / 0.0 ms  last resort 


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x3aa1a529cca1 <JSObject>
    1: /* anonymous */(aka /* anonymous */) [/Users/nmatsumoto4/Documents/rails/workspace/test_app/node_modules/webpack/lib/Stats.js:~329] [pc=0x10c36db915da](this=0x3aa1a5282241 <undefined>,reason=0x42ae7414e09 <ModuleReason map = 0x16a59415d9b1>)
    2: arguments adaptor frame: 3->1
    3: map(this=0x3276e1f42849 <JSArray[1]>)
    4: fnModule(aka fnModule) [/Users/nmatsumoto4/Documents/rails/work...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: node::Abort() [/usr/local/Cellar/node/7.7.3/bin/node]
 2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/usr/local/Cellar/node/7.7.3/bin/node]
 3: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/local/Cellar/node/7.7.3/bin/node]
 4: v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/usr/local/Cellar/node/7.7.3/bin/node]
 5: v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/Cellar/node/7.7.3/bin/node]
 6: 0x10c36d1840dd
Done in 129.49s.


即時コンパイルできないと、いちいちコーディング後にbin/webpackerを実行しなければなりません(最初の一回は比較的メモリを使わないので)
そうなるとかなり開発効率が落ちるしストレスが半端ないです。絶対に解決してやろう。 と思いしばらく格闘していました。

原因

以下にあるように、old space領域のメモリが規定値(デフォルトでは1.4G)を超えたためになります。

原因
[39191:0x102801c00]   128125 ms: Mark-sweep 1401.3 (1456.1) -> 1401.3 (1456.1) MB, 469.1 / 0.0 ms  allocation failure GC in old space requested

対策

肝心の対策ですが、考えられる手として、以下のどちらかと思います。

1.コンパイルに利用されるメモリ量を減らす
2.old spaceの領域を増やす

1について色々漁ってみましたが、根本解決できるような解決方法は特にありませんでした。
よって、2の対策法をとります。

Node起動時にwebpacker-dev-serverが利用するold-spaceを規定値(1.4G)から増やします
変更箇所は以下になります。

node_module/.bin/webpacker-dev-server(変更前)
#!/usr/bin/env
node_module/.bin/webpacker-dev-server(変更後)
#!/usr/bin/env node --max-old-space-size=8192

どうせなんで8Gくらいに増やしてみました。これでOOMが起きなくなり、巨大なプロジェクトでもOOMが起きなくなりました。
解決!

ただ、node_moduleに記載するのでちょっと気持ち悪いですね。。。。
他に同じ体験された解決された方がいらっしゃいましたら教えていただけると嬉しいです!

参考

Process out of memory - Webpack #1914
npm searchの「JavaScript heap out of memory」エラー対応

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.