部署“react-admin”应用程序时,Heroku 服务器因“JavaScript 堆内存不足”而崩溃

Posted

技术标签:

【中文标题】部署“react-admin”应用程序时,Heroku 服务器因“JavaScript 堆内存不足”而崩溃【英文标题】:Heroku server crashes with "JavaScript heap out of memory" when deploying 'react-admin' app 【发布时间】:2020-03-30 23:56:51 【问题描述】:

我目前正在使用“react-admin”开发一个管理面板,该面板在我的本地运行良好,但是一旦我将应用程序上传到 Heroku,构建就会失败并出现以下错误:“FATAL ERROR: Ineffective mark-compacts接近堆限制分配失败 - javascript 堆内存不足”

我已将问题缩小到最初的import Admin from 'react-admin';,方法是设置一个干净的项目,其中仅包含“react-admin”包和一个简单的 Admin 导入。一旦我尝试使用该组件,部署就会失败并出现“内存不足”错误。

还有其他人遇到过这个问题吗?

这是我的 package.json:


  "name": "mrewards_admin",
  "version": "0.1.0",
  "private": true,
  "dependencies": 
    "axios": "^0.19.0",
    "deepmerge": "^4.2.2",
    "prop-types": "^15.7.2",
    "react": "^16.12.0",
    "react-admin": "^3.0.2",
    "react-dom": "^16.12.0",
    "react-scripts": "3.2.0"
  ,
  "engines": 
    "node": "13.0.1"
  ,
  "scripts": 
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  ,
  "eslintConfig": 
    "extends": "react-app"
  ,
  "browserslist": 
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  

这是 Heroku 的日志输出:

2019-12-06T00:29:07.000000+00:00 app[api]: Build succeeded
2019-12-06T00:29:10.340460+00:00 heroku[web.1]: State changed from starting to up
2019-12-06T00:29:10.135608+00:00 app[web.1]: ℹ 「wds」: Project is running at http://172.18.103.22/
2019-12-06T00:29:10.135999+00:00 app[web.1]: ℹ 「wds」: webpack output is served from /
2019-12-06T00:29:10.136098+00:00 app[web.1]: ℹ 「wds」: Content not from webpack is served from /app/public
2019-12-06T00:29:10.136196+00:00 app[web.1]: ℹ 「wds」: 404s will fallback to /index.html
2019-12-06T00:29:10.136405+00:00 app[web.1]: Starting the development server...
2019-12-06T00:29:10.136409+00:00 app[web.1]:
2019-12-06T00:30:46.302146+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/" host=test-react-admin.herokuapp.com request_id=b7cafb3a-311c-4ef2-bd61-cb1f863e69ca fwd="216.81.49.130" dyno=web.1 connect=1ms service=30000ms status=503 bytes=0 protocol=https
2019-12-06T00:30:47.234363+00:00 app[web.1]:
2019-12-06T00:30:47.234390+00:00 app[web.1]: <--- Last few GCs --->
2019-12-06T00:30:47.234392+00:00 app[web.1]:
2019-12-06T00:30:47.234413+00:00 app[web.1]: [30:0x492c940]    98675 ms: Scavenge 240.7 (257.5) -> 239.8 (257.7) MB, 1.7 / 0.0 ms  (average mu = 0.238, current mu = 0.037) allocation failure
2019-12-06T00:30:47.234415+00:00 app[web.1]: [30:0x492c940]    98685 ms: Scavenge 240.7 (257.7) -> 239.9 (258.0) MB, 1.9 / 0.0 ms  (average mu = 0.238, current mu = 0.037) allocation failure
2019-12-06T00:30:47.234418+00:00 app[web.1]: [30:0x492c940]    98903 ms: Mark-sweep 240.8 (258.0) -> 237.9 (258.0) MB, 211.0 / 0.1 ms  (average mu = 0.350, current mu = 0.474) allocation failure scavenge might not succeed
2019-12-06T00:30:47.234419+00:00 app[web.1]:
2019-12-06T00:30:47.234421+00:00 app[web.1]:
2019-12-06T00:30:47.234422+00:00 app[web.1]: <--- JS stacktrace --->
2019-12-06T00:30:47.234423+00:00 app[web.1]:
2019-12-06T00:30:47.234426+00:00 app[web.1]: ==== JS stack trace =========================================
2019-12-06T00:30:47.234427+00:00 app[web.1]:
2019-12-06T00:30:47.234429+00:00 app[web.1]: 0: ExitFrame [pc: 0x1374fd9]
2019-12-06T00:30:47.234431+00:00 app[web.1]: Security context: 0x2a1cf61808a1 <JSObject>
2019-12-06T00:30:47.234433+00:00 app[web.1]: 1: _next2(aka _next2) [0x2546e8465cf9] [0x1b716e9004a9 <undefined>:~21] [pc=0x1d633e40a0e8](this=0x1b716e9004a9 <undefined>)
2019-12-06T00:30:47.234440+00:00 app[web.1]: 2: /* anonymous */(aka /* anonymous */) [0x2546e8465ea1] [0x1b716e9004a9 <undefined>:46] [bytecode=0x6238003a241 offset=37](this=0x1b716e9004a9 <undefined>,0x1b716e9004a9 <undefined>,0x1b716e9004a9 <undefined>)
2019-12-06T00:30:47.234441+00:00 app[web.1]: 3: _next1(aka _ne...
2019-12-06T00:30:47.234443+00:00 app[web.1]:
2019-12-06T00:30:47.234445+00:00 app[web.1]: FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
2019-12-06T00:30:47.234453+00:00 app[web.1]:
2019-12-06T00:30:47.245340+00:00 app[web.1]: Writing Node.js report to file: report.20191206.003047.30.0.001.json
2019-12-06T00:30:47.245345+00:00 app[web.1]: Node.js report completed
2019-12-06T00:30:47.245828+00:00 app[web.1]: 1: 0x9da7c0 node::Abort() [node]
2019-12-06T00:30:47.246377+00:00 app[web.1]: 2: 0x9db976 node::OnFatalError(char const*, char const*) [node]
2019-12-06T00:30:47.246963+00:00 app[web.1]: 3: 0xb39f1e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
2019-12-06T00:30:47.247418+00:00 app[web.1]: 4: 0xb3a299 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
2019-12-06T00:30:47.247992+00:00 app[web.1]: 5: 0xce5635  [node]
2019-12-06T00:30:47.248561+00:00 app[web.1]: 6: 0xce5cc6 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [node]
2019-12-06T00:30:47.249102+00:00 app[web.1]: 7: 0xcf1b5a v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [node]
2019-12-06T00:30:47.249627+00:00 app[web.1]: 8: 0xcf2a65 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
2019-12-06T00:30:47.250190+00:00 app[web.1]: 9: 0xcf5478 v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [node]
2019-12-06T00:30:47.250701+00:00 app[web.1]: 10: 0xcbbda7 v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType) [node]
2019-12-06T00:30:47.251301+00:00 app[web.1]: 11: 0xff1e0b v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
2019-12-06T00:30:47.251959+00:00 app[web.1]: 12: 0x1374fd9  [node]
2019-12-06T00:30:47.285408+00:00 app[web.1]: npm ERR! code ELIFECYCLE
2019-12-06T00:30:47.285920+00:00 app[web.1]: npm ERR! errno 1
2019-12-06T00:30:47.287473+00:00 app[web.1]: npm ERR! ra-test@0.1.0 start: `react-scripts start`
2019-12-06T00:30:47.287759+00:00 app[web.1]: npm ERR! Exit status 1
2019-12-06T00:30:47.288057+00:00 app[web.1]: npm ERR!
2019-12-06T00:30:47.288300+00:00 app[web.1]: npm ERR! Failed at the ra-test@0.1.0 start script.
2019-12-06T00:30:47.288528+00:00 app[web.1]: npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
2019-12-06T00:30:47.295555+00:00 app[web.1]:
2019-12-06T00:30:47.295669+00:00 app[web.1]: npm ERR! A complete log of this run can be found in:
2019-12-06T00:30:47.295759+00:00 app[web.1]: npm ERR!     /app/.npm/_logs/2019-12-06T00_30_47_289Z-debug.log
2019-12-06T00:30:47.344869+00:00 heroku[web.1]: Process exited with status 1
2019-12-06T00:30:47.369971+00:00 heroku[web.1]: State changed from up to crashed

谢谢!

【问题讨论】:

我在尝试使用 Google App Engine 进行部署时也有同样的经历,所以绝对不是 Heroku 问题。 这对我有用Error with running ReactJS/TailwindCSS/Heroku: React Refresh runtime should not be included in the production bundle 这篇文章帮助我解决了我的问题Error with running ReactJS/TailwindCSS/Heroku: React Refresh runtime should not be included in the production bundle 这篇文章帮助了我Error with running ReactJS/TailwindCSS/Heroku: React Refresh runtime should not be included in the production bundle 【参考方案1】:

联系了heroku支持,我解决了这个问题:

发生错误是因为节点在遇到 JavaScript 堆内存不足错误之前只能寻址 1.5GB 内存,这是它从 V8 引擎继承的默认限制。我们通过 NODE_OPTIONS env var 调整 Heroku 上的默认设置,以便进程可以处理所有可用内存:https://github.com/heroku/heroku-buildpack-nodejs/blob/master/lib/environment.sh#L29-L33

一种选择是在调用节点时专门调用 --max_old_space_size=2560 以查看这是否有助于缓解问题。您可以通过运行以下命令将该选项通过环境变量传递给 Node:

$ heroku config:set NODE_OPTIONS="--max_old_space_size=2560" -a [app_name]

还将构建脚本调整为:

"scripts": 
    "start": "node --max_old_space_size=2560 node_modules/.bin/react-scripts start",
    "build": "node --max_old_space_size=2560 node_modules/.bin/react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  

虽然不确定构建和启动脚本更改会产生影响。

【讨论】:

我试过了,它奏效了!谢谢。我不认为构建脚本调整是必要的,因为通过 cli 运行 heroku config 命令会在启动之间更新与您的应用程序关联的配置变量(您可以从 heroku 设置选项卡 devcenter.heroku.com/articles/… 中看到) 在我的mac上,当我使用这个命令时它导致dquote&gt; ,我还访问了heroku设置选项卡,并且没有添加配置变量,请告诉这个dquote是什么?? 你的命令需要更正,小逗号问题不是大问题,正确的命令是heroku config:set NODE_OPTIONS='--max_old_space_size=2560 -a [app-name]' (我现在已经编辑了帖子以删除多余的尾随双引号。) 这是为我做的,非常感谢。学到了一些新东西。【参考方案2】:

我能够完成这项工作的唯一方法是升级到付费测功机并将我的 package.json 中的脚本更改为:

"scripts": 
    "start": "node --max_old_space_size=2048 node_modules/.bin/react-scripts start",
    "build": "node --max_old_space_size=2048 node_modules/.bin/react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  

不确定是否需要更改脚本。在部署期间,内存使用量跃升至 1Gb 以上

【讨论】:

【参考方案3】:

首先我评论了Inovramadani 答案并试图改进那个答案,但是当我发现不止一个问题时,我决定给出我自己的答案。在 Heroku 日志中,我也收到此错误消息 Node 不允许 -a 标志,因此正确的命令是

heroku config:set NODE_OPTIONS='--max_old_space_size=2560 [app-name]'

【讨论】:

为什么 [app-name] 在引号内而不是在引号外? 它应该在引号内,但显然你会将 [app-name] 替换为引号内的原始应用名称 很确定这很混乱; -a [app-name]heroku config:set 命令本身的一部分,而不是值的一部分。另一个答案最后有一个额外的",我会修复【参考方案4】:

如果您使用的是免费的测功机版本。请将您的 package.json start 脚本更改为:

"start": "node --optimize_for_size --max_old_space_size=460 dist/main.js",

更多信息在这里:https://devcenter.heroku.com/articles/node-memory-use

【讨论】:

【参考方案5】:

我找到了一个完美的解决方案。

我刚刚降级了一些属性的版本: "react-dom": "^16.13.0""react-scripts": "3.4.0"package.json 文件中,在 Heroku 中就像魅力一样工作。

原解决方案来源:https://bismobaruno.medium.com/fixing-memory-heap-reactjs-on-heroku-16910e33e342

【讨论】:

以上是关于部署“react-admin”应用程序时,Heroku 服务器因“JavaScript 堆内存不足”而崩溃的主要内容,如果未能解决你的问题,请参考以下文章

react-admin 与下一个 js

仪表板上的 React-admin 组件?

如何在 React Typescript 应用程序中导入 react-admin?

如何在 react-admin 中禁用乐观 UI 更新?

登录前后将 react-admin 应用与捆绑包拆分的代码

导入 react-admin 中断 tsc 构建