Как предотвратить исчерпание памяти узлу при объединении js для React Native
При связывании js для React Native с использованием ClojureScript я получил следующую ошибку. Кажется, что узлу не хватает памяти при связывании комплекта javascript. Это, вероятно, более вероятно случится при использовании ClojureScript, так как результирующие файлы js обычно больше, чем 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
4 ответа
Решение для iOS заключается в редактировании следующего файла: ios/YourProjectName.xcodeproj/project.pbxproj
и измените следующую строку (~600)
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
в
shellScript = "export NODE_BINARY='node --max_old_space_size=4092'\n../node_modules/react-native/packager/react-native-xcode.sh";
Для android это также можно установить в android/app/build.gradle, добавив:
project.ext.react = [
// override which node gets called and with what additional arguments
nodeExecutableAndArgs: ["node", "--max-old-space-size=4096"]
]
обратите внимание, что это должно быть добавлено над следующей строкой:
apply from: "../../node_modules/react-native/react.gradle"
Я нашел способ создать подписанный APK в ренатальном проекте. Для этого мы должны отредактировать файл в node_modules/react-native/react.gradle
Измените 84-ую строку в этом файле. От
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)
К этому
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)
Для создания производственной сборки вы должны использовать
lein prod-build
После компиляции ClojureScript используйте следующие команды:
cd android && ./gradlew assembleRelease
Сгенерированный APK можно найти под android/app/build/outputs/apk/app-release.apk
и готов к распространению.
Другой обходной путь - отключить оптимизацию, установив --dev true
для производственных сборок. Это имеет недостатки производительности, но по моему опыту они приемлемы. Режим разработки также позволяет выполнять ряд проверок во время выполнения. Вы можете отключить их, изменив константу DEV в верхней части вывода пакета, например:
#!/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()))
За iOS
, с react-native 0.59.0 работает путем редактирования наios/YourProjectName.xcodeproj/project.pbxproj
эта линия
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
с участием
shellScript = "export NODE_OPTIONS=--max_old_space_size=4096\n../node_modules/react-native/scripts/react-native-xcode.sh";