webpack3から4にアップデートしてみた
年末に業務でwebpack3で動いてたものを4系にアップデートしたので時代遅れな話題かもだけどやったことを書いてみる。
何故アップデートしたの?
StorybookやJestなどを導入してみようと思ったときに、今の資産だと4系ではないからキツかったのが原因だ。あと、ローカル環境でのビルドも平均5秒程度掛かっており少し減らせないかなと考えやってみた。
webpack5の動向も気になる時期なのに何をやっているんだろう感もあるが。。
構成
CLIではないVue.jsを使用している。webpack自体はbaseのwebpackの他にSTG環境用、Prod環境用(本番)と存在している。
├── build/
│ ├── build.js # 本番環境で動かす
│ ├── check-versions.js # バージョンをチェックする
│ ├── staging.js # 結合環境で動かす
│ ├── vue-loader.conf.js # ヘッダーの通知のタイマー処理
│ ├── utils.js # cssのローディング周りの設定など
│ ├── webpack.base.conf.js # どの環境でもベースとなるwebpack
│ ├── webpack.dev.conf.js # npm scriptで最初に呼ばれるwebpack
│ ├── webpack.stg.conf.js # 結合環境でのwebpack
│ ├── webpack.prod.conf.js # 本番環境でのwebpack
STG環境と本番環境の違いはenvの部分が違うだけで後はほぼ一緒。
進め方
基本的には
-
webpackを4にバージョンアップする
-
babelのバージョンアップをする
-
その時出たエラーを解消していく
という手順になる。
先人の知恵があるので基本的には問題なく進められると思う。
お世話になった参照記事
vue init webpackで作成したプロジェクトをwebpack4に移行する
基本この2つでエラーに対しては、Stack Overflowで検索すれば基本出てくる。
- webpack4からcliと機能が分離されているのでインストール
npm install webpack-cli --save-dev
- package.jsonのwebpackのバージョンを変更してupdate
"webpack": "^4.26.0"
この時vue-routerなどもupdateする。
- modeオプションを追加する。
webpack4からmodeオプションが追加されている。これで今までNODE_ENVで設定していたものが使わなくなる。また開発時はdevelopment、公開時はproductionにしてnpm scriptの記述も変える
npm script
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"build": "node build/build.js webpack --mode=production",
webpack.prod.conf.js
mode: 'production',
- mini-css-extract-pluginの追加
webpack3まで使っていたextract-text-webpack-pluginは非推奨なためmini-css-extract-pluginをインストールして記述を変更する。
build/webpack.prod.conf.js
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
allChunks: true,
ignoreOrder: true
}),
build/utils.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
if (options.extract) {
return ['vue-style-loader', MiniCssExtractPlugin.loader].concat(loaders)
} else {
return ['vue-style-loader'].concat(loaders)
}
- optimization系の設定 mode指定している場合はminifyされるが、UglifyJsPluginを使用している場合はoptimization.minimizerの中に処理を移す必要がある。OptimizeCSSPluginも処理を移動する。
CommonsChunkPluginはv4だと削除となりSplitChunksPluginになっている
さらに、optimization.runtimeChunkを記述してmanifest.jsとして出力するように設定する。
optimization: {
runtimeChunk: {
name: 'manifest'
},
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
})
],
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: "vendor",
chunks: "all"
}
}
}
}
- VueLoaderPluginの追加 build/webpack.base.conf.jsに以下を追加する。
const VueLoaderPlugin = require('vue-loader/lib/plugin')
plugins: [
new VueLoaderPlugin()
],
babelのバージョンアップ
babel6だったので7にアップデートしていく。参照記事は以下 https://babeljs.io/docs/en/v7-migration
上記を読んで何となく全体感を把握したがbabel7から懐疑的な変更が入っているため色々修正していく。
- 以下が必要だったのでインストールしていく。
npm install --save-dev @babel/core @babel/preset-env babel-loader
- webpackの記述を以下に修正する。
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
}
]
},
- .babelrcからbabel.config.jsに変更 babel.config.jsで以下を記述していく。.babelrcは削除する。
module.exports = function (api) {
api.cache(true);
const presets = [
["@babel/preset-env", {
corejs: 3,
modules: false,
useBuiltIns: "usage"
}]
];
return {
presets,
};
}
- エントリーポイントのmain.jsにbabelをimportする。
import 'core-js/stable'
import 'regenerator-runtime/runtime'
IE11対応
これだけだと、IE11環境でエラーとなってしまい、表示できなかったのでbabel.config.jsのuseBuiltInsをentryに変更、targetsにie11を指定。
※entryを指定すると、全polyfillをimportしてしまうのでファイルサイズが肥大化してしまう。polyfill.ioなどに移行も検討する必要がある。
module.exports = function (api) {
api.cache(true);
const presets = [
["@babel/preset-env", {
corejs: 3,
modules: false,
useBuiltIns: "entry",
targets: {
ie: 11
}
}]
];
return {
presets,
};
}
これで完了だと思いきや今回のpackageの中のnode_modules内に.vue
ファイルがあり、その中の処理でアロー関数が使用されていたためIE11環境でSCRIPTエラーとなっていた。対象のpackageはvue-quill-editor
import {quillEditor as QuillEditor} from 'vue-quill-editor'
上記のimport先をnode_modules内のdist内にあるコンパイル済みのファイルに指定してあげることで解決。cssについてはコンパイルされていないので別でimportする必要があった。
import { quillEditor as QuillEditor } from 'vue-quill-editor/dist/vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
vue-routerのバージョンアップで起きたエラー
3.1.1にアップデートしたところ以下のissueのエラーに出くわした。
https://github.com/vuejs/vue-router/issues/2872
router.pushする箇所で以前まではコールバックがない状態だとグローバルなrouterにエラーを送信していたが、3.1.1から個別のrouterにエラーが送られるようになったっぽい。実際にコンソールエラーが表示されていた。
これを解消するには、issueの通り以下を追加していく。
.catch(err => {})
これで解決した。検索とかするUIで何度も同じrouter.pushする箇所があると発生する。
感想
IE11対応すると途端につらくなる。ファイルサイズも大きくなるし。残対応としては次は、ファイルサイズを減らしていくチューニングする作業をしていく。