安装 webpack-cli ,升级webpack
npm i --save-dev webpack webpack-cli
在执行上述命令之后,webpack还是3.x的版本,那很可能是你的package-lock.json中锁定了webpack的最高版本。所以我们直接指定webpack4.x的版本进行安装。
npm i --save-dev webpack@4
- 安装之前
- 安装之后
重新安装node包
此时运行npm run dev ,项目会出现Error:Cannot find module 'array-includes'错误
解决办法:
- 删掉项目中的node_modules文件夹,
- 执行 npm cache clean 或者 cnpm cache clean 命令清除掉cache缓存,
- 然后cnpm install 和npm run dev就可以在这台电脑运行你的项目
升级webpack-dev-server至3.X
此时我们运行npm run dev,会发现报错:Error: Cannot find module ‘webpack/bin/config-yargs’
这是由于webpack-dev-server的版本和webpack4的版本不兼容导致的,webpack3对应的最高webpack-dev-server版本为2.11.5,所以我们要安装2.11.5以上的版本。查阅npm官网,安装目前webpack4对应最新的webpack-dev-server版本为3.11.1
npm i webpack-dev-server@3.11.1 --save-dev
如果安装完后运行依旧报这个错误的话,则需要查看webpack-cli的版本是不是过高。
解决:
- 卸载当前的 webpack-cli npm uninstall webpack-cli
- 安装 webpack-cli 3.* 版本 npm install webpack-cli@3 -D
升级html-webpack-plugin
安装完毕之后,再次执行npm run dev,发现之前的报错消失了。但是又有新的错误提示:compilation.mainTemplate.applyPluginsWaterfall is not a function
这是因为html-webpack-plugin 版本不兼容导致的,所以我们需要升级一下html-webpack-plugin。
npm i html-webpack-plugin@3 -D
升级vue-loader
安装完毕之后,再次执行npm run dev,发现之前的报错消失了。但是又有新的错误提示:
*Module build failed (from ./node_modules/vue-loader/index.js):
TypeError: Cannot read property ‘vue’ of undefined*
这是因为vue-loader的版本不兼容webpack4导致的,所以我们升级一下vue-loader
npm i vue-loader@15 -D
增加VueLoaderPlugin插件代码
安装完毕之后,再次执行npm run dev,发现之前的报错消失了。但是又有新的错误提示:
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.
File was processed with these loaders:
- ./node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
这里是因为最新版的 vue-loader 需要加一个新的配置 VueLoaderPlugin。
打开webpack.dev.conf.js,增加如下代码,…表示省略部分已有的代码
//webpack.dev.conf.js
...
// 引入
const { VueLoaderPlugin } = require('vue-loader')
...
// 找到plugins数组,增加一个数组项
plugins: [
...
new VueLoaderPlugin()
]
然后打开webpack.prod.conf.js,进行同样的修改:
// webpack.prod.conf.js
...
// 引入
const { VueLoaderPlugin } = require('vue-loader')
...
// 找到plugins数组,增加一个数组项
plugins: [
...
new VueLoaderPlugin()
]
安装babel-plugin插件转换es6代码。
安装完毕之后,再次执行npm run dev,发现之前的报错消失了。项目似乎已经可以正常运行了。但,打开项目地址一看,一片空白。F12控制台一样,鲜红的报错:
Uncaught TypeError: Cannot assign to read only property ‘exports’ of object ‘#
点开报错信息,发现直指BaseClient.js,该文件是node_modules下webpack-dev-server中的文件。经过查询得知,出现该种报错信息的原因是因为混用了import和module.exports,一个是es6的用法,一个是es5的用法。
网上的解决办法是建议统一使用es6或者es5的写法 。但是这里的文件并不是我写的,而是npm插件中生成的,所以肯定不能修改写法。于是想到了是不是没有配置babel转换导致的。
安装以下插件
npm install babel-plugin-transform-es2015-modules-commonjs -D
在项目根目录的.babelrc文件中加入:
"plugins": ["transform-es2015-modules-commonjs"]
同时安装webpack webpack-dev-server webpack-cli
安装完后再次运行项目,报错信息:'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
解决方法:
现在使用webpack要同时安装webpack-cli这个包,才可以调用webpack和webpack-dev-server这些命令。
cnpm install webpack webpack-dev-server webpack-cli --save-dev
安装完后再次运行项目,打开项目地址,ok,终于可以正常运行了!
至此,dev环境下的修改已经全部完成。
简单来说就是编译时,遇到can not find xxx,can not find xxx 此类的错误,就需要升级对应的插件,倒也还好。
可能会出现某些模块找不到的错误
这可能是复制的问题,删除 node_modules 文件夹重新安装一次就好了应该是 node_modules 文件夹有些文件复制不过去。
配置optimization.splitChunks,删除optimize.CommonsChunkPlugin
接下来还得继续配置product环境,执行npm run build ,依然是醒目的报错信息:
Error: webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead.
这是因为webpack4已经弃用了webpack.optimize.CommonsChunkPlugin插件,改用了config.optimization.splitChunks属性来进行更加灵活的配置。
打开webpack.prod.conf.js,找到plugins同级的位置增加以下代码。
// plugins
const webpackConfig = merge(baseWebpackConfig, {
module: {...},
optimization: { // 增加此处代码
// Setting optimization.runtimeChunk to true adds an additonal chunk to each entrypoint containing only the runtime.
// The value single instead creates a runtime file to be shared for all generated chunks.
runtimeChunk: 'single',
minimize: env === 'production' ? true : false, //生产环境下才进行代码压缩。
splitChunks:{
//As it was mentioned before this plugin will affect dynamic imported modules. Setting the optimization.
//splitChunks.chunks option to "all" initial chunks will get affected by it (even the ones not imported dynamically).
//This way chunks can even be shared between entry points and on-demand loading.
//This is the recommended configuration.
//官方推荐使用all.
chunks: 'all',
minSize: 30000, //模块大于30k会被抽离到公共模块
minChunks: 1, //模块出现1次就会被抽离到公共模块
maxAsyncRequests: 5, //异步模块,一次最多只能被加载5个
maxInitialRequests: 3, //入口模块最多只能加载3个
name: true, // 拆分出来块的名字(Chunk Names),默认由块名和hash值自动生成;设置为true则表示根据模块和缓存组秘钥自动生成。
cacheGroups: {
// 详情建议参看官网 http://webpack.html.cn/plugins/split-chunks-plugin.html
default: {
minChunks: 2,
reuseExistingChunk: true,
},
//打包重复出现的代码
vendor: {
// chunks: 'initial',
// 省略test默认选择所有的模块。
chunks: 'all',
minChunks: 2,
name: 'vendor'
},
//打包第三方类库
commons: {
// chunks: "initial",
chunks: "all",
name: "commons",
minChunks: Infinity
}
}
}
},
plugins: [...]
})
同时,注释或者删除plugins中含有CommonsChunkPlugin的代码,应该是3块:
// 去掉 plugins 中的这3部分代码
...
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
...
升级extract-text-webpack-plugin到4.0.0,或者去除extract-text-webpack-plugin,安装 mini-css-extract-plugin
再次执行npm run build,发现之前的报错信息没有了,但是仍然有新的报错提示:
Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead
这里是因为官方已经不推荐使用 extract-text-webpack-plugin 提取 css 样式,可以使用 mini-css-extract-plugin 替代
如果不想改变的话可以升级 extract-text-webpack-plugin到4.0.0-beta.0版本。
cnpm install extract-text-webpack-plugin@next --save-dev
使用mini-css-extract-plugin,因为它可以根据页面按需加载,分割css代码,使得以前一大坨CSS彻底成为过去式。
首先安装mini-css-extract-plugin
npm i mini-css-extract-plugin -D
然后卸载extract-text-webpack-plugin
npm uninstall extract-text-webpack-plugin
然后去除所有和extract-text-webpack-plugin相关的代码。一共有2处位置需要修改:
第一个是utils.js中的:
// utils.js
'use strict'
...
// const ExtractTextPlugin = require('extract-text-webpack-plugin') //删除或注释此段。
// 引入
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
...
// 修改此处的generateLoaders函数。
// generate loader string to be used with extract text plugin
function generateLoaders(loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
/**注释或删除此处代码,开始 */
// return ExtractTextPlugin.extract({
// use: loaders,
// publicPath: '../../',
// fallback: 'vue-style-loader'
// })
/**注释或删除此处代码,结束 */
/**增加此处代码开始 */
return [MiniCssExtractPlugin.loader].concat(loaders)
/**增加此处代码结束 */
} else {
return ['vue-style-loader'].concat(loaders)
}
}
第二处是webpack.prod.conf.js中的:
...
//webpack.prod.conf
/**注释或删除此处代码,开始 */
// const ExtractTextPlugin = require('extract-text-webpack-plugin')
/**注释或删除此处代码,结束 */
/**增加此处代码,开始 */
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
/**增加此处代码,结束 */
...
plugins:[
...
/**注释或删除此处代码,开始 */
// extract css into its own file
// new ExtractTextPlugin({
// filename: utils.assetsPath('css/[name].[contenthash].css'),
// // Setting the following option to `false` will not extract CSS from codesplit chunks.
// // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
// allChunks: true,
// }),
/**注释或删除此处代码,结束 */
/**增加此处代码,开始 */
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
allChunks: true,
}),
/**增加此处代码,结束 */
...
]
我这里使用的是升级extract-text-webpack-plugin,因为使用mini-css-extract-plugin导致的css-loder版本问题一直没有找到合适的方法,网上大部分是要去掉minimize这个属性,4.0的脚手架,安装的css-loader是3.2版本的所以没有这个属性。网上找到一种方式是降级到0.28.0版本,我的项目还是打包不成,这个也暂时搁浅了。同学们有好的方法可以私聊我(#^.^#)
更换追加hash的方式
继续打包之前的错误没了,但是又出现了新的问题。还是webPack 升级到 4.x导致extract-text-webpack-plugin 无法使用
解决方法:
再次运行npm run build,这次终于运行成功了!
在打包的时候可能会出现一个新的错误。
网上好多人说加一个属性:minimize: true,过滤掉错误信息。不过好像没什么用。删掉项目中的node_modules文件夹,重新安装一次就可以解决这个问题了。至此,vue/cli2下的webpack3升级webpack4工作已经全部完成,希望对那些需要升级的同学有帮助ღ( ´・ᴗ・` )比心