一、問題描述
執行npm run build
之后報錯:
報錯信息:
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
之前一直是好的,加了以下代碼之后出錯: 1.dev_server.js中加了一個entry ``` entry: { ..., "report.phantom.zeus":[ HOT_MIDDLEWARE_ENTRY, path.resolve(PATHS.app, './views/effect/zeus/report-view/report.phantom.js') ] }
2.webpack.config.common.js中加了一個entry
entry: {
...,
"report.phantom.zeus":[
path.resolve(PATHS.app, './views/effect/zeus/report-view/report.phantom.js')
]
}
3.webpack.config.prod.js中加了一個plugins
plugins: [
...,
new HtmlwebpackPlugin({
chunks:['report.phantom.zeus', 'vendor'],
hash:true,
template:'build/report-zeus.html',
filename: 'report-zeus.html'
})
]
<br />
`npm run build`命令實際執行的一串命令集:
<br />
npm run clean:dist & npm run build:config & cross-env BABEL_ENV=production webpack -p --config ./build/webpack.config.prod.js --progress & npm run zip
## 二、原因分析
將`npm run build`命令集進行拆分,可分成四步:
- npm run clean:dist
- npm run build:config
- cross-env BABEL_ENV=production webpack -p --config ./build/webpack.config.prod.js --progress
- npm run zip
看報錯信息是在第三步報錯的。
<br />
報錯之前和之后的變化,共三處代碼發生變化,經過測試發現是在 webpack.config.common.js 文件中加的 entry 的影響:
entry: {
...,
"report.phantom.zeus":[
path.resolve(PATHS.app, './views/effect/zeus/report-view/report.phantom.js')
]
}
增加一個 entry 意味着 webpack 編譯的成本加大,看報錯信息:
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
也是JavaScript堆內存溢出,`CALL_AND_RETRY_LAST`這個模塊分配失敗
<br />
查看下內存使用情況,執行`npm run build`之前內存占用7.87GB,執行之后一直上升直到大概10GB:
<br />

<br />

<br />
看起來機器的內存似乎並沒有撐爆,那為什么會內存溢出呢?
<br />
Google搜索報錯信息:
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
<br />
搜索到以下比較有用的文章:
https://itbilu.com/nodejs/core/Ey_SnYXnx.html
https://github.com/npm/npm/issues/12741
https://github.com/nodejs/node/issues/10137
https://stackoverflow.com/questions/38558989/node-js-heap-out-of-memory
https://github.com/webpack/webpack/issues/1914
<br />
提到的解決方案都是在`node`命令后面加`--max-old-space-size=4096`這個參數:
`node --max-old-space-size=4096`
<br />
解決方案截圖:
<br />




<br />
可是`npm run build`命令集里並沒有`node`命令,怎么加呢?
<br />
在前端大神warpig的指點下,了解到`npm`、`webpack`等命令其實縮寫命令,實際的命令前面是要加`node`命令的。
<br />
所以`npm run build`命令中出錯的命令:
cross-env BABEL_ENV=production webpack -p --config ./build/webpack.config.prod.js --progress
其實應該是:
cross-env BABEL_ENV=production node webpack -p --config ./build/webpack.config.prod.js --progress
<br />
但直接運行這個命令會報錯,提示`cross-env`這個命令不存在,經查詢發現`cross-env`只是為了解決node環境變量的問題。
<br />
運行`node webpack -p --config ./build/webpack.config.prod.js --progress`,還是報錯:
<br />

<br />
當前路徑下找不到webpack模塊,改成:
node node_modules/webpack/bin/webpack.js -p --config ./build/webpack.config.prod.js --progress
就可以。
<br />
加上指定V8引擎所占用的內存空間的參數`--max-old-space-size=4096`:
node --max-old-space-size=4096 node_modules/webpack/bin/webpack.js -p --config ./build/webpack.config.prod.js --progress
編譯成功。
<br />
在package.json中也加上這個參數,重新執行`npm run build`,打包成功。
<br />
一句話總結:
> webpack打包時,由於要編譯的內容太多,占用了過多內存(大概10GB-7.86GB=`2.14GB`),而在64位操作系統下,V8引擎(node運行環境)默認內存只有大約`1.43GB`(1.4G新生代內存+32MB老生代內存),`2.14GB>1.43GB`,導致內存溢出。
## 三、解決方案
`webpack` 改成 `node --max-old-space-size=4096 node_modules/webpack/bin/webpack.js`
<br />
所以`npm run build`執行的是以下命令集:
npm run clean:dist & npm run build:config & cross-env BABEL_ENV=production node --max-old-space-size=4096 node_modules/webpack/bin/webpack.js -p --config ./build/webpack.config.prod.js --progress & npm run zip
## 四、參考資料
https://itbilu.com/nodejs/core/Ey_SnYXnx.html
https://github.com/webpack/webpack/issues/1914