はい。
タイトルに答え書いてます!
TL;DR
- CircleCIでWebpackのビルドプロセスが落ちており原因がCPUかメモリーっぽいとき
- JSの縮小化処理で使ってる
terser-webpack-plugin
のparalell
に並列数を明示的に指定すれば解決する!(かもしれない) - ここに書いてる
https://webpack.js.org/plugins/terser-webpack-plugin/#parallel
問題
- Circle CIで実行してたwebpackのビルドが頻繁に落ちるようになった
#!/bin/bash -eo pipefail
yarn build
yarn run v1.22.0
$ APP_STAGE=$ENV_NAME run-s clean copy-assets build:webpack
$ rimraf build
$ cpx "src/assets/**/*" ./build
$ webpack --config webpack/config.base.js --mode production
Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade caniuse-lite browserslist`
Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade`
Too long with no output (exceeded 10m0s): context deadline exceeded
こんな感じで普通に10分のデフォルトタイムアウトで落ちる
- Circle CIにSSHでログインして手でビルドコマンド叩くと数十秒で正常に終わる
- topコマンドなどで確かめるとnodeのプロセスはかなり動いてCPUに負荷がかかっており、loadaverageも高まっているので思い処理だというのは分かる。
- なぜ手動だといけるのか。。。
調査、検証
タイムアウトを伸ばす
- 言うて動くときは動くのでギリギリ10分超えたのではないか
- ->えーいとりあえず伸ばしてみよう
- ->30分まで伸ばす
- 終わらない
いろんなもののバージョンを上げてみよう
- 何かのバグにはまってて実は最新版なら解消されてる説
- 上げたもの
- webpack 4.29.5 -> 4.42.0
- 結果: 効果なし
- node 10系 -> 12系
- docker imageを更新
- 結果: 動いた!何回かやっても問題なし!
- webpack 4.29.5 -> 4.42.0
解決?
- と思ったら数日後また同じエラーが戻ってきた。。なぜ、、、
Webpackチューニング調査
- 挙動的にはどう考えてもWebpackの処理の重さが原因だ
- 巷に溢れてるチューニング施策を探して実施してみよう、、!
- 色々調べて見た結果。。。
解決策発見!
-
どうやら重いのはJS縮小化の処理くさい
- 縮小化で使われている
terser-webpack-plugin
にparalell
オプションがある。 - CircleCI上でtop見た時にかなりの数のnodeプロセス動いてたんで、並列で動いていると勝手に勘違いしていたのですが、どうやらそういうわけではない。
- 縮小化で使われている
-
・・・というか、もろここに書いてるのですが、CircleCIのような実際のCPU数が提供されないような環境ではparalell数を直指定する必要があるとのこと。
-
paralell: true
ではだめです。あくまで数指定。
⚠️ If you use Circle CI or any other environment that doesn't provide real available count of CPUs
then you need to setup explicitly number of CPUs to avoid `Error: Call retries were exceeded`
というわけでこんな感じの設定をWebpackの設定ファイルにterser-webpack-pluginの設定を追加すれば良いです。
※webpack4以降ではmode=productionでビルドすれば特に縮小化の設定はいらないわけですが、実際terser-webpack-plugin
が動いているようでオプション設定したい場合はこのような指定が必要です。
const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: 6 // 6は適当です。環境に応じて変えてください。
})
]
}
}
プロセッサの数はCircleCI上でこれらのコマンドで調べられるので参考にすればよいですが、かなり多く出ると思うのでWebpackのビルドくらいなら使い切るほど指定する必要も無いとは思います。(規模による)
# CPU ごとのコアの数
grep cpu.cores /proc/cpuinfo | sort -u
# 論理プロセッサーの数
grep processor /proc/cpuinfo | wc -l
まとめ
ぐぐっても全然解決策が引っかからず途方にくれたので、少しでも同じ問題に当たった人の助けになればと思い雑に書き残しました。