vue.config.js配置优化相关记录
一、通用版
const webpack = require('webpack')
const TerserPlugin = require('terser-webpack-plugin')
const CompressionPlugin = require('compression-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const proName = '/gdyb-h5/'
const envTime = new Date().getTime()
const baseUrl = process.env.VUE_APP_BASE_API
const envName = process.env.VUE_APP_MODE || 'sit'
const proEnv = envName === 'pro'
const cdnList = {
css: ['cdnList/css/vant_2.12.37_index_min.css'],
js: [
'cdnList/js/vue_2.6.11_min.js',
'cdnList/js/vue-vuex_3.4.0_min.js',
'cdnList/js/vue-router_3.6.5_min.js',
'cdnList/js/lib-flexible_0.3.2_min.js',
'cdnList/js/axios_0.24.0_min.js',
'cdnList/js/crypto-js_4.1.1_min.js',
'cdnList/js/better-scroll_2.4.2_min.js',
'cdnList/js/moment_2.29.1_min.js',
// 'cdnList/js/echars_5.2.2_min.js',
'cdnList/js/html2-canvas_1.0.0-rc.4_min.js',
'cdnList/js/signature_pad_3.0.0-beta4_min.js'
// 'cdnList/js/tinymce_5.10.2_min.js',
// 'cdnList/js/vue-tinymce_1.1.2_min.js'
]
}
module.exports = {
publicPath: proName,
assetsDir: 'static',
filenameHashing: false,
productionSourceMap: !proEnv,
css: {
extract: true,
sourceMap: !proEnv,
loaderOptions: {
sass: {
additionalData: `
@import "@/assets/scss/variable.scss";
@import "@/assets/scss/mixin.scss";
`
}
}
},
pages: {
index: {
title: 'gdyb-h5',
cdnList: cdnList,
filename: 'index.html',
entry: './src/main.js',
template: './public/index.html',
chunks: ['chunk-vendors', 'chunk-common', 'index']
}
},
chainWebpack: config => {
// 避免加载多余无用资源
config.plugins.delete('prefetch')
config.plugins.delete('preload')
const minimizer = proEnv ? [new TerserPlugin()] : []
config.optimization = Object.assign(config.optimization, {
minimize: true,
minimizer: minimizer,
splitChunks: {
chunks: 'all'
}
})
// CSS压缩
const miniCssExtractPlugin = new MiniCssExtractPlugin({
filename: 'static/css/[name].[hash:8].css',
chunkFilename: 'static/css/[name].[hash:8].css'
})
config.plugin('mini-css-extract-plugin').use(miniCssExtractPlugin)
// config.plugin('extract-css').use(miniCssExtractPlugin)
// image按需加载
config.module.rule('images')
.test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
disable: !!proEnv,
bypassOnDebug: true
})
.end()
},
configureWebpack: (config) => {
if (proEnv) {
config.devtool = false
// 打包分析
config.plugins.push(new BundleAnalyzerPlugin())
}
// CND去除打包依赖项
config.externals = {
vue: 'Vue',
vuex: 'Vuex',
'vue-router': 'VueRouter',
'lib-flexible': 'lib',
axios: 'axios',
'crypto-js': 'CryptoJS',
'better-scroll': 'BetterScroll',
moment: 'moment',
// echarts: 'echarts',
html2canvas: 'html2canvas',
// tinymce: 'tinymce',
// 'vue-tinymce': 'VueTinymce',
signature_pad: 'SignaturePad'
}
// 输出文件名
config.output = Object.assign(config.output, {
publicPath: proName,
filename: `static/js/[name]-${envTime}.js`,
chunkFilename: `static/js/[name]-${envTime}.js`
})
// 兼容依赖
config.entry.app = ['babel-polyfill', './src/main.js']
// 公共代码抽离
// config.optimization = {
// splitChunks: {
// cacheGroups: {
// common: {
// name: 'chunk-common',
// chunks: 'initial',
// minSize: 0,
// minChunks: 2
// },
// vendor: {
// name: 'chunk-vendors',
// priority: 1,
// test: /node_modules/,
// chunks: 'initial',
// minSize: 0,
// minChunks: 2
// }
// }
// }
// }
config.optimization.splitChunks = {
chunks: 'async',
minChunks: 2,
minSize: 20 * 1024,
maxSize: 200 * 1024
// minSizeReduction: 30 * 1024 // 至少缩小bundle体积限制:如果生成chunk不会减小总bundle体积,则不生成, [webpack5+]
}
// 开启Gzip压缩
const compression = new CompressionPlugin({
algorithm: 'gzip',
filename: '[path].gz[query]',
test: /\.js$|\.html$|\.css$|\.scss$/,
minRatio: 1,
threshold: 10240,
deleteOriginalAssets: false
})
const limitChuck = new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 60,
minChunkSize: 1000
})
config.plugins.push(compression, limitChuck)
// config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true
},
devServer: {
proxy: baseUrl
}
}
二、改良版
const webpack = require('webpack')
const CompressionPlugin = require('compression-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const proName = '/gdyb-h5/'
const envTime = new Date().getTime()
const baseUrl = process.env.VUE_APP_BASE_API
const envName = process.env.VUE_APP_MODE || 'sit'
const proEnv = envName === 'pro'
const cdnList = {
css: ['cdnList/css/vant_2.12.37_index_min.css'],
js: [
'cdnList/js/vue_2.6.11_min.js',
'cdnList/js/vue-vuex_3.4.0_min.js',
'cdnList/js/vue-router_3.6.5_min.js',
'cdnList/js/lib-flexible_0.3.2_min.js',
'cdnList/js/axios_0.24.0_min.js',
'cdnList/js/crypto-js_4.1.1_min.js',
'cdnList/js/better-scroll_2.4.2_min.js',
'cdnList/js/moment_2.29.1_min.js',
'cdnList/js/html2-canvas_1.0.0-rc.4_min.js',
'cdnList/js/signature_pad_3.0.0-beta4_min.js'
// 'cdnList/js/echars_5.2.2_min.js',
// 'cdnList/js/tinymce_5.10.2_min.js',
// 'cdnList/js/vue-tinymce_1.1.2_min.js'
]
}
module.exports = {
publicPath: proName,
assetsDir: 'static',
filenameHashing: false,
productionSourceMap: !proEnv,
css: {
extract: true,
sourceMap: !proEnv,
loaderOptions: {
sass: {
additionalData: `
@import "@/assets/scss/variable.scss";
@import "@/assets/scss/mixin.scss";
`
}
}
},
pages: {
index: {
title: 'gdyb-h5',
cdnList: cdnList,
filename: 'index.html',
entry: './src/main.js',
template: './public/index.html',
chunks: ['index', 'chunk-common', 'chunk-vendors', 'chunk-tinymce', 'chunk-echarts', 'chunk-pdfh5']
}
},
configureWebpack: (config) => {
// 生产开启配置
if (proEnv) {
config.devtool = false
// 模块拆分
config.optimization.splitChunks = {
cacheGroups: {
common: {
name: 'chunk-common',
chunks: 'async',
minChunks: 2,
minSize: 20 * 1024,
maxSize: 200 * 1024
},
vendor: {
name: 'chunk-vendors',
chunks: 'async',
priority: 1,
test: /[\\/]node_modules[\\/]/,
minSize: 0,
minChunks: 2
},
vue: {
name: 'chunk-vuejs',
test: /[\\/]node_modules[\\/]_?vue(.*)/,
priority: 20
},
echarts: {
name: 'chunk-echarts',
test: /[\\/]node_modules[\\/]_?echarts(.*)/,
priority: 50,
chunks: 'async'
},
pdfh5: {
name: 'chunk-pdfh5',
test: /[\\/]node_modules[\\/]_?pdfh5(.*)/,
priority: 50,
chunks: 'async'
},
tinymce: {
name: 'chunk-tinymce',
test: /[\\/]node_modules[\\/]_?tinymce(.*)/,
priority: 50,
chunks: 'async'
},
}
}
// 打包分析
config.plugins.push(new BundleAnalyzerPlugin())
}
// CND去除打包依赖项
config.externals = {
vue: 'Vue',
vuex: 'Vuex',
'vue-router': 'VueRouter',
'lib-flexible': 'lib',
axios: 'axios',
'crypto-js': 'CryptoJS',
'better-scroll': 'BetterScroll',
moment: 'moment',
html2canvas: 'html2canvas',
signature_pad: 'SignaturePad'
// echarts: 'echarts',
// tinymce: 'tinymce',
// 'vue-tinymce': 'VueTinymce',
}
// 输出文件名
config.output = Object.assign(config.output, {
publicPath: proName,
filename: `static/js/[name]-${envTime}.js`,
chunkFilename: `static/js/[name]-${envTime}.js`
})
// 兼容依赖
config.entry.app = ['babel-polyfill', './src/main.js']
// 开启Gzip压缩
const compression = new CompressionPlugin({
algorithm: 'gzip',
filename: '[path].gz[query]',
test: /\.js$|\.html$|\.css$|\.scss$/,
minRatio: 1,
threshold: 10240,
deleteOriginalAssets: false
})
const limitChuck = new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 60,
minChunkSize: 1000
})
config.plugins.push(compression, limitChuck)
},
devServer: {
proxy: baseUrl
}
}
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。