How to prevent node from running out of memory when bundling js for React Native

4.1k views Asked by At

When bundling js for React Native using ClojureScript I got the following error. It seems that node runs out of memory when bundling the javascript bundle. This is probably more likely to happen when using ClojureScript since the resulting js files are generally bigger than vanilla js.

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

<--- Last few GCs --->

  152689 ms: Mark-sweep 1369.3 (1434.8) -> 1362.8 (1434.8) MB, 2794.5 / 0 ms [allocation failure] [GC in old space requested].
  155498 ms: Mark-sweep 1362.8 (1434.8) -> 1362.9 (1434.8) MB, 2808.4 / 0 ms [allocation failure] [GC in old space requested].
  158508 ms: Mark-sweep 1362.9 (1434.8) -> 1362.8 (1434.8) MB, 3010.8 / 0 ms [last resort gc].
  161189 ms: Mark-sweep 1362.8 (1434.8) -> 1362.8 (1434.8) MB, 2680.5 / 0 ms [last resort gc].


<--- JS stacktrace --->

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

Security context: 0xd4b9fdc9e59 <JS Object>
    1: visitQueue [/Users/myproj/node_modules/babel-traverse/lib/context.js:~130] [pc=0x3e89a3f7bd28] (this=0x24a5ec659101 <a TraversalContext with map 0x157972399611>,queue=0x24a5ec659149 <JS Array[1]>)
    2: node [/Users/myproj/node_modules/babel-traverse/lib/index.js:~150] [pc=0x3e89a3e4f23a] (this=0x387a6b7f4301 <JS Function traverse (SharedFunction...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

<--- Last few GCs --->

  238422 ms: Mark-sweep 1364.8 (1434.8) -> 1364.8 (1434.8) MB, 3377.7 / 0 ms [allocation failure] [GC in old space requested].
  241834 ms: Mark-sweep 1364.8 (1434.8) -> 1364.8 (1434.8) MB, 3412.3 / 0 ms [allocation failure] [GC in old space requested].
  245313 ms: Mark-sweep 1364.8 (1434.8) -> 1364.8 (1434.8) MB, 3478.7 / 0 ms [last resort gc].
  248639 ms: Mark-sweep 1364.8 (1434.8) -> 1364.8 (1434.8) MB, 3326.4 / 0 ms [last resort gc].


<--- JS stacktrace --->

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

Security context: 0x266dabec9e59 <JS Object>
    1: new constructor(aka NodePath) [/Users/myproj/node_modules/babel-traverse/lib/path/index.js:~61] [pc=0x108980041705] (this=0x1cedf9a7ef69 <a NodePath with map 0x3182f379cf21>,hub=0x266dabe04189 <undefined>,parent=0x3d43337ab49 <a Node with map 0x3182f3798489>)
    3: get [/Users/myproj/node_modules/babel-traverse/lib/path/index.js:~87] [pc=0x10898...

[node-haste] Encountered an error while persisting cache:
> Error: Uncaught error in the transformer worker: /Users/myproj/node_modules/react-native/packager/transformer.js
>     at _transform.then.catch.error (/Users/myproj/node_modules/react-native/packager/react-packager/src/JSTransformer/index.js:99:31)
>     at tryCallOne (/Users/myproj/node_modules/promise/lib/core.js:37:12)
>     at /Users/myproj/node_modules/promise/lib/core.js:123:15
>     at flush (/Users/myproj/node_modules/asap/raw.js:50:29)
>     at _combinedTickCallback (internal/process/next_tick.js:67:7)
>     at process._tickCallback (internal/process/next_tick.js:98:9)
/Users/myproj/node_modules/promise/lib/done.js:10
      throw err;
      ^

Error: Uncaught error in the transformer worker: /Users/myproj/node_modules/react-native/packager/transformer.js
    at _transform.then.catch.error (/Users/myproj/node_modules/react-native/packager/react-packager/src/JSTransformer/index.js:99:31)
    at tryCallOne (/Users/myproj/node_modules/promise/lib/core.js:37:12)
    at /Users/myproj/node_modules/promise/lib/core.js:123:15
    at flush (/Users/myproj/node_modules/asap/raw.js:50:29)
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickCallback (internal/process/next_tick.js:98:9)
Command /bin/sh failed with exit code 1
5

There are 5 answers

3
vikeri On BEST ANSWER

The solution for iOS is to edit the following file: ios/YourProjectName.xcodeproj/project.pbxproj and change the following line (~600)

shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";

to

shellScript = "export NODE_BINARY='node --max_old_space_size=4092'\n../node_modules/react-native/packager/react-native-xcode.sh";
1
Slowyn On

I have found way to generate Signed APK in re-natal project. For this we must edit file in node_modules/react-native/react.gradle

Change 84-th row in this file. From

commandLine(*nodeExecutableAndArgs, "node_modules/react-native/local-cli/cli.js", "bundle", "--platform", "android", "--dev", "${devEnabled}",
    "--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraPackagerArgs)

To this

commandLine(*nodeExecutableAndArgs, "--max-old-space-size=4096", "node_modules/react-native/local-cli/cli.js", "bundle", "--platform", "android", "--dev", "${devEnabled}",
    "--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraPackagerArgs)

To create production build you must use

lein prod-build

After compiling of ClojureScript use this commands:

cd android && ./gradlew assembleRelease

The generated APK can be found under android/app/build/outputs/apk/app-release.apk, and is ready to be distributed.

0
Daniel Hopkins On

For android, this can also be set in android/app/build.gradle by adding:

project.ext.react = [
   // override which node gets called and with what additional arguments
   nodeExecutableAndArgs: ["node", "--max-old-space-size=4096"]
]

note that this must be added above the following line:

apply from: "../../node_modules/react-native/react.gradle"
0
loevborg On

Another workaround is to disable optimizations by setting --dev true for production builds. This has performance drawbacks, but in my experience they are acceptable. Dev mode also enables a number of runtime checks. You can disable them by changing the DEV constant at the top of the bundle output, like so:

#!/usr/bin/env python

# Patch jsbundle to set __DEV__ to false

import sys, re

print(re.sub(r'__DEV__\s*=\s*true;', "__DEV__=false;",
        sys.stdin.read()))
0
manuela trotti On

For iOS, with react-native 0.59.0 works by editing on ios/YourProjectName.xcodeproj/project.pbxproj

this line

shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";

with

shellScript = "export NODE_OPTIONS=--max_old_space_size=4096\n../node_modules/react-native/scripts/react-native-xcode.sh";