当前项目是经过当时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']
复制代码