- 升級後速度有明顯的提升
- webpack升級優化參考文章:webpack4.0打包優化策略、讓你的Webpack起飛—考拉會員後臺Webpack優化實戰
- 本文內容為升級優化過程中遇到的 Warning、 Error、及以上文章未講到處
升級前
webpack版本:3.6.0
五次打包所需時間:83.57s、78.71s、77.08s、78.07s、92.22s
升級後
五次打包所需時間:71.44s、37.54s、30.05s、30.50s、32.68s.
開始升級
一. 升級webpack到4.x
同時還需升級:
$ yarn add webpack
$ yarn add webpack-cli
$ yarn add webpack-dev-server
複製程式碼
二.升級vue-loader
-
如果在
yarn dev/yarn build
時出現以下Error:Error: [vue-loader] vue-template-compiler must be installed as a peer dependency, or a compatible compiler implementation must be passed via options. 複製程式碼
解決方法: 是vue版本與vue-template-compiler不一致。升級vue版本試試
-
將vue-loader引入webpack配置
// 檔案: wepack.base.conf.js + const { VueLoaderPlugin } = require('vue-loader') + module.exports = { ...., plugins:[ new VueLoaderPlugin() ] } 複製程式碼
三.使用mini-css-extract-plugin
來提取css
// 檔案:wepack.prod.conf.js
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+ new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[contenthash:8].css'),
chunkFilename: utils.assetsPath('css/[name].[contenthash:8].css')
})
複製程式碼
四.升級vue-router
由於 vue-loader@13.0.0 版本中對模組匯入做了更新,為了支援 Webpack3 中的 Scope Hoisting 屬性,esModule 被預設設定為了 true,如果你之前用到require來匯入*.vue檔案,請注意:
const Foo = require('./Foo.vue')
// 需要改為
const Foo = require('./Foo.vue').default
// 或者直接使用
const Foo = import('./Foo.vue')
複製程式碼
在低於 Vue 2.4 和 vue-router 2.7 的版本中,import 語法需要修改為:
const Foo = () => import('./Foo.vue')
// 需要改為
const Foo = () => import('./Foo.vue').then(m => m.default)
複製程式碼
五.關於使用import('./Foo.vue')
匯入模組所面臨的問題 【參考】
- 由於webpack的import實現機制,會將其他的.vue檔案打包,導致開發環境的熱更新變的比較慢
- 所以要區分開發環境和生產環境。開發環境使用
require
,生產環境使用import
使用babel 的 plugins:babel-plugin-dynamic-import-node。它可以將所有的import()轉化為require()。
// 首先先安裝
yarn add cross-env babel-plugin-dynamic-import-node -D
複製程式碼
cross-env
包能夠提供一個設定環境變數的scripts,能跨平臺地設定及使用環境變數。
-
在
package.json
中增加BABEL_ENV
"dev": "cross-env BABEL_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.js" 複製程式碼
-
在
.babelrc
檔案中加入babel-plugin-dynamic-import-node
{ "env": { "development": { "plugins": ["dynamic-import-node"] } } } 複製程式碼
六.其他關於依賴升級後遇到的問題
由autoprefixer
版本引起的 warning
Module Warning (from ./node_modules/postcss-loader/lib/index.js):
(Emitted value instead of an instance of Error) autoprefixer: /xxx/xxx.vue:187:6: Second Autoprefixer control comment was ignored. Autoprefixer applies control comment to whole block, not to next rules.
複製程式碼
解決方法:
// 將樣式中像下面的寫法
/* autoprefixer: off */
....
/* autoprefixer: on */
// 改為
/* autoprefixer: ignore next */
複製程式碼
如果使用了script-ext-html-webpack-plugin
,要注意與html-webpack-plugin
的版本相容
如果出現的異常如下:
(node:24424) UnhandledPromiseRejectionWarning: Error: Cyclic dependency
(node:24424) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:24424) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
複製程式碼
這是迴圈依賴導致的。預設情況下html-webpack-plugin
的配置項chunksSortMode
的值是auto
,需要改為none
new HtmlWebpackPlugin({
filename: '',
template: 'index.html',
inject: true,
favicon: resolve('favicon.ico'),
title: '',
path: '',
minify: {
...
},
chunksSortMode: 'none'
}
)
複製程式碼
但是修改後會出現問題:
chunksSortMode
決定你 chunks 的載入順序,如果設定為none,你的 chunk 在頁面中載入的順序就不能夠保證了,可能會出現樣式被覆蓋的情況。比如在app.css裡面修改了一個第三方庫element-ui的樣式,通過載入順序的先後來覆蓋它,但由於設定為了none,打包出來的結果會變成下面這樣:
<link href="/newapp/static/css/app.48599466.css" rel="stylesheet">
<link href="/newapp/static/css/chunk-elementUI.6a2cdc9f.css" rel="stylesheet">
<link href="/newapp/static/css/chunk-libs.dc4401e2.css" rel="stylesheet">
複製程式碼
app.css
被先載入了,之前寫的樣式覆蓋就失效了 。
解決方法: chunksSortMode
屬性去掉,升級html-webpack-plugin:"4.0.0-alpha"
和script-ext-html-webpack-plugin:"2.0.1"
修改後如果出現以下異常:
/xxx/node_modules/script-ext-html-webpack-plugin/lib/plugin.js:50
compilation.hooks.htmlWebpackPluginAlterAssetTags.tap(PLUGIN, alterAssetTags);
^
TypeError: Cannot read property 'tap' of undefined
複製程式碼
- 修改"html-webpack-plugin": "^4.0.0-alpha" => "4.0.0-alpha"
- 刪除 node_modules
- 刪除 package-lock.json
- npm install/yarn