在基於vue-cli2.0腳手架開發的項目至今已經有一年半的時間了,由於業務在不斷迭代的關係,項目的代碼已經達到8w行了,從而致使了webpack打包編譯的速度愈來愈慢。爲了項目的長治久安,我決心要對這個項目中的webpack進行升級與優化。javascript
vue-cli2.0集成了Webpack3,可是在當前Webpack5都呼之欲出的狀況下,Webpack3顯然就顯得太老了,並且新版本自己就是對老版本的優化和加強,與其花精力在老版本上作優化爲何不在新版本上這麼作呢?站在巨人肩膀上的感受難道很差麼?css
yarn add webpack webpack-cli
複製代碼
yarn add webpack-dev-server -D
複製代碼
yarn add postcss-loader@3.0.0 css-loader@3.2.0 vue-style-loader@4.1.2 vue-loader@15.7.1 -D
複製代碼
修改webpack.base.conf.js中的vue-loader解析規則html
//const vueLoaderConfig = require('./vue-loader.conf')
const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
...,
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
// options: vueLoaderConfig
},
]
},
plugins: [
new VueLoaderPlugin()
]
}
複製代碼
yarn add html-webpack-plugin@3.2.0 -D
複製代碼
若是存在如下錯誤,那是因爲extract-text-webpack-plugin不兼容webpack4形成,官方推薦的使用mini-css-extract-plugin來替換使用。vue
yarn add mini-css-extract-plugin@0.8.0 -D
複製代碼
修改utils.jsjava
// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
exports.cssLoaders = function (options) {
...
// Extract CSS when that option is specified
// (which is the case during production build)
// if (options.extract) {
// return ExtractTextPlugin.extract({
// use: loaders,
// fallback: 'vue-style-loader',
// publicPath: '../../', //注意: 此處根據路徑, 自動更改,添加publicPath,能夠在css中使用背景圖
// })
// } else {
// return ['vue-style-loader'].concat(loaders)
// }
return [
options.extract ? {loader:MiniCssExtractPlugin.loader, options: {publicPath: '../../'}} : 'vue-style-loader',
].concat(loaders)
}
複製代碼
修改webpack.prod.conf.jsnode
//const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const webpackConfig = merge(baseWebpackConfig, {
...,
plugins: [
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
allChunks: true,
}),
// 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,
// }),
]
})
複製代碼
在webpack.dev.conf.js中添加mode:「development」,並移除NamedModulesPlugin,NoEmitOnErrorsPlugin插件,webpack4已修改成內置插件。webpack
module.exports = {
...,
mode: "development",
...,
plugins: {
//new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
//new webpack.NoEmitOnErrorsPlugin(),
}
}
複製代碼
在dev環境下運行,發現報錯,咱們能夠經過修改webpack.base.conf.js中的配置來解決。git
module.exports = {
...
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader'
// include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
include: [resolve('src'),resolve('test')],
exclude: /node_modules/
},
]
}
}
複製代碼
這樣的咱們的dev環境就算升級成功了github
在webpack.prod.conf.js中添加mode: "production"web
const webpackConfig = merge(baseWebpackConfig, {
...,
plugins: [
//new webpack.optimize.CommonsChunkPlugin(),
//new webpack.optimize.CommonsChunkPlugin({}),
//new webpack.optimize.CommonsChunkPlugin({}),
//new webpack.optimize.ModuleConcatenationPlugin(),
//new OptimizeCSSPlugin({}),
//new UglifyJsPlugin({})
],
})
複製代碼
再刪除webpack.prod.conf.js中的部分插件
const webpackConfig = merge(baseWebpackConfig, {
...,
optimization: {
//取代 new UglifyJsPlugin
minimizer: [
// 壓縮代碼
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false,
drop_debugger: true,//關閉debug
drop_console: true,//關閉console
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// 可本身配置,建議第一次升級先不配置
new OptimizeCSSPlugin({
// cssProcessorOptions: config.build.productionSourceMap
// ? {safe: true, map: {inline: false}, autoprefixer: false}
// : {safe: true}
}),
],
// 識別package.json中的sideEffects以剔除無用的模塊,用來作tree-shake
// 依賴於optimization.providedExports和optimization.usedExports
sideEffects: true,
// 取代 new webpack.optimize.ModuleConcatenationPlugin()
concatenateModules: true,
// 取代 new webpack.NoEmitOnErrorsPlugin(),編譯錯誤時不打印輸出資源。
noEmitOnErrors: true,
splitChunks: {
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
chunks: 'initial',
name: 'vendors',
},
'async-vendors': {
test: /[\\/]node_modules[\\/]/,
minChunks: 2,
chunks: 'async',
name: 'async-vendors'
}
}
},
runtimeChunk: { name: 'runtime' }
},
})
複製代碼
最後再production環境下打包,若是出現下面這樣的結果說明咱們