當前項目是經過當時Vue-CLI 2.x
生成使用,配置是babel 6
編譯、webpack 3.x
打包。因爲項目發展到某個階段,須要升級優化。目標是打包速度更快、bundle體積更小。
本文經過分享代碼片斷講述部分版本升級後的不一樣以及可能發生的報錯案例,達到讓小夥伴們能找到對應的解決辦法,減小升級版本的恐懼感。css
經過配置 mode
,可選 production
生產環境 和 development
開發環境。html
移除 loaders,使用 rules 代替vue
// webpack.base.config.js
module: {
- loaders: {}
+ rules: {}
}
複製代碼
插件 CommonsChunkPlugin
替換成配置 optimization.splitChunks
和 optimization.runtimeChunk
參考:webpack.js.org/plugins/spl…
原 webpack 3
CommonsChunkPlugin
插件:node
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: 2
}),
// webpack 相關代碼打包到一個文件
// 新模塊加入給新模塊加一個id
// 規避長緩存問題
new webpack.optimize.CommonsChunkPlugin({
name: 'runtime'
})
複製代碼
現 webpack 4
替代者 splitChunks
& runtimeChunk
:webpack
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
name: 'vendor',
minChunks: 2
// 可選 'initial | async | all',
// 分別表明,初始化時加載、異步加載、二者皆使用
chunks: 'all'
// 表明權重值,值越大,打包優先級越高
priority: 10
}
}
},
runtimeChunk: {
name: 'runtime'
}
}
複製代碼
production
生產環境下簡化配置,默認開啓插件 UglifyJsPlugin
git
// webpack.prod.config.js
module.exports = {
+ mode: 'production',
- plugins: [
- new UglifyJsPlugin(/* ... */),
- new webpack.DefinePlugin({
- "process.env.NODE_ENV": JSON.stringify("production") }),
- new webpack.optimize.ModuleConcatenationPlugin(),
- new webpack.NoEmitOnErrorsPlugin()
- ]
}
複製代碼
固然,生產環境依然能夠經過配置關閉 UglifyJsPlugin
github
optimization: {
minimize: false
}
複製代碼
development
// webpack.dev.config.js
devServer: {
open: true, // 自動打開瀏覽器頁面
host: 'xxx.xxx.com', // host
openPage: 'xxx' // 路徑
historyApiFallback: true // 啓用 history模式
proxy: 'xxx' // 代理配置
}
複製代碼
package.json
因爲開發環境的devServer使用方式有變化,因此 package.json
的 scripts
也須要修改,不然會報以下錯誤:
ERROR in Entry module not found: Error: Can't resolve './src' in 'E:\workspace'
正確修改配置:web
// package.json
{
"scripts": {
- "dev": "node build/dev-server.js",
+ "dev": "webpack-dev-server --config build/webpack.dev.config.js"
}
}
複製代碼
若是小夥伴正在使用如下插件,請按詳情變動使用,而且可能出現報錯解決:shell
vue-loader v15
① 從 v14 遷移npm
// webpack.base.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
// ...
plugins: [
new VueLoaderPlugin()
]
}
複製代碼
thread-loader
原本打算使用 HappyPack
,但是vue-loader@15 不徹底支持 HappyPack。
如今這個Issue已經關閉,因此小夥伴能夠繼續嘗試用 HappyPack
進行優化,記得反饋哦。
eslint-loader v5
若有eslint報錯以下:
cannot read property 'eslint' of undefined
添加配置:
plugins: [
new webpack.LoaderOptionsPlugin({ options: {} })
]
複製代碼
若有警告以下:
[ESLINT_LEGACY_OBJECT_REST_SPREAD] DeprecationWarning. The 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' option is deprecated. Use 'parserOptions.ecmaVersion' instead
修改配置:
// .eslintrc.js
parserOptions: {
parse: 'babel-eslint',
ecmaVersion: 8,
- ecmaFeatures: {
- experimentalObjectRestSpread: true
- }
}
複製代碼
copy-webpack-plugin
若有報錯以下: TypeError: compilation.contextDependencies.push is not a function
升級插件
npm i copy-webpack-plugin@latest -D
複製代碼
html-webpack-plugin v4 若是小夥伴使用 html-webpack-plugin
提供的鉤子擴展了本身定義的插件,可能會發生如下錯誤:
① Plugin could not be registered at 'html-webpack-plugin-before-html-generation'. Hook was not found. BREAKING CHANGE: There need to exist a hook at 'this.hooks'.
② TypeError: callback is not a function
③ this.htmlWebpackPlugin.getHooks is not a function
緣由:這三者都是由於升級版本或者使用hooks的方式改變了而致使。
參考:
www.npmjs.com/package/htm…
github.com/jantimon/ht…
解決:
//plugin.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
class MyPlugin {
apply (compiler) {
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
console.log('The compiler is starting a new compilation...')
// Staic Plugin interface |compilation |HOOK NAME | register listener
HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
'MyPlugin', // <-- Set a meaningful name here for stacktraces
(data, cb) => {
// Manipulate the content
data.html += 'The Magic Footer'
// Tell webpack to move on
cb(null, data)
}
)
})
}
}
module.exports = MyPlugin
複製代碼
mini-csss-extract-plugin
這是在咱們的項目升級過程當中,最容易出現問題的插件。
① 修改Vue-CLI 2
生成關於處理樣式的 utils.js
以下:
// const ExtractTextPlugin = require("extract-text-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
...
// 找到:
- if (options.extract) {
- //options.extract = NODE_ENV === 'production'
- return ExtractTextPlugin.extract({
- use: loaders,
- fallback: 'vue-style-loader'
- })
- } else {
- return ['vue-style-lodaer'].concat(loaders))
- }
+ return [options.extract ?
+ MiniCssExtractPlugin.loader :
+ 'vue-style-loader'
+ ].concat(loaders)
複製代碼
② 報錯:document is not defined
解決:區分環境使用 mini-css-extract-plugin(production) 和 vue-style-loader(development),如 ① 配置便可
③ 報錯:cannot read property pop of undefined
緣由:是webpack optimize時候產生的,小編也只知其一;不知其二,很差解釋。
參考:
④ 警告:[mini-css-extract-plugin] Conflicting order between
緣由:不一樣CSS模塊裏,引入同一個CSS,而引入的順序不同產生的警告。
參考:github.com/webpack-con…
解決:屏蔽警告
// 安裝依賴
npm i -D webpack-filter-warnings-plugin
// 配置插件
plugins: {
new FilterWarningsPlugin({
exclude: /mini-css-extract-plugin[^]*Conflicting order between:/,
})
}
複製代碼
⑤ 疑惑:打包後,產生不少小的css文件,能不能把他們都打包成一個css文件
緣由:vue-loader@15 會把 <style lang="less">
看成 *.less
參考:vue-loader.vuejs.org/zh/migratin…
解決:棄用 mini-css-extract-plugin
,重用 extract-text-webpack-plugin
並升級版本。且把utils.js
的配置如原來升級前。
npm i -D extract-text-webpack-plugin@next
複製代碼
可是,這裏可能會產生報錯,以下: Error: Path variable [contenthash:8] not implemented in this context: [name]_[contenthash:8].css
緣由:插件的臨時版本@next
並不支持contenthash
。 參考:github.com/webpack-con…
解決:
plugins: [
new ExtractTextPlugun({
- filename: '[name].[contenthash:8].css'
+ filename: '[md5:contenthash:hex:20]'
}})
]
複製代碼
注意,如今extract-text-webpack-plugin已經不更新了,因此最好仍是使用官方推薦的 mini-css-extract-plugin
。
script-text-html-webpack-plugin
緣由:插件暫不支持 webpack4,將會在 v2版 實現
解決:使用preload-webpack-plugin
You may need an appropriate loader to handle this file type
緣由:package.json
裏安裝依賴變化了,可是因爲 package-lock.json
存在。
解決辦法:
全局配置一勞永逸:
npm config set package-lock false
複製代碼
解決當前項目:
刪除 package-lock.json
、node_modules
,從新執行命令 npm install
__webpack_hmr 404 not found
緣由:webpack 配置 entry 數組裏面有 build/dev-client
的配置
解決:刪除這個配置便可
部分文件內做用域 this = undefined
緣由:不明
解決:this 改成 window
warn: entrypoint = undefined
解決:不用理會
# 不安裝到本地而是直接運行命令,npm 的新功能
npx babel-upgrade --write
# 或者常規方式
npm i babel-upgrade -g
babel-upgrade --write
# 更新 babel 配置 而且 安裝依賴
npx babel-upgrade --write --install
複製代碼
這裏區分需不須要編譯 node_modules
裏面的依賴。
若是須要,刪除項目根目錄下 .babelrc
改成使用 babel.config.js
@babel/preset-env
並按需引入 polyfill
@babel/polyfill
babel-polyfill
Promise
等ES6語法,在 Android 4.4如下 和 IE 的兼容問題// node 環境
require('@babel/polyfill')
// ES6 main.js
import('@babel/polyfill')
// webpack.base.config.js
entry: ['@babel/polyfill', 'main.js']
複製代碼