webpack打包优化(vue)

:使用 vue-cli 自动构建的项目,没有webpack的设置文件;需要更改webpack 设置可以在vue.config.js中进行修改
configureWebpack:返回一个对象
chainWebpack:函数的链式操作

const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
const path = require('path')
function resolve(dir){
return path.join(__dirname,dir)
}
module.exports = {
publicPath: './', // router hash 模式使用
outputDir: 'dist',//输出内容的文件夹
assetsDir: 'static',//编译内容的文件夹
productionSourceMap: false,// 打包时不会生成 .map 文件,加快打包速度
lintOnSave: false ,//关闭格式检查
devServer: { // 开发服务器
host: needHost,
port: port,
open: false,
overlay: {
warnings: false,
errors: true
},
proxy: {
'/api': {
target: 'xxxxxxx',
secure: false,
changeOrigin: true, //是否跨域
logLevel: 'debug',
pathRewrite: {
'^/api': '' // pathRewrite 表示的意思是 把/api 替换为空
}
}
}
},
configureWebpack: {
optimization: {
runtimeChunk: true
},
plugins: [
new ScriptExtHtmlWebpackPlugin({
inline: /runtime~.+\.js$///正则匹配runtime文件名
})
]
},
chainWebpack: config => {
// set preserveWhitespace
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.compilerOptions.preserveWhitespace = true
return options
}).end()
config.when(process.env.NODE_ENV === 'development', config => config.devtool('cheap-source-map')) // 设置调试查看源代码
config.optimization.splitChunks({
chunks:'all',
cacheGroups:{
commons:{
name:'chunk-commons',
test:resolve('src/components'),
minChunks:3,
priority:5,
reuseExistingChunk:true
},
libs:{
name:'chunk-libs',
chunks:'initial',
test:/[\\/]node_modules[\\/]/,
priority:10
}
}
})
config.plugin('preload')
.tap(args => {
args[0].fileBlacklist.push(/runtime~.+\.js$/) //正则匹配runtime文件名,去除该文件的preload
return args
})
}
}
工具模块
const path = require('path')
function resolve(dir){
return path.join(__dirname,dir)
}
基础配置
publicPath: './', // router hash 模式使用
outputDir: 'dist',//输出内容的文件夹
assetsDir: 'static',//编译内容的文件夹
productionSourceMap: false,// 打包时不会生成 .map 文件,加快打包速度
lintOnSave: false ,//关闭格式检查
开发服务器代理
devServer: { // 开发服务器
host: needHost,
port: port,
open: false,
overlay: {
warnings: false,
errors: true
},
proxy: {
'/api': {
target: 'xxxxxxx',
secure: false,
changeOrigin: true, //是否跨域
logLevel: 'debug',
pathRewrite: {
'^/api': '' // pathRewrite 表示的意思是 把/api 替换为空
}
}
}
},
快捷引用
// resolve.alias 设置引入别名
config.resolve.alias
.set('@', resolve('src'))
.set('assets', resolve('src/assets'))
.set('api', resolve('src/api'))
.set('views', resolve('src/views'))
.set('components', resolve('src/components'))
preserveWhitespace
vue打包保留标签的空白
cheap-source-map
根据环境变量, 设置调试查看源代码
/*
source-map:一种 提供源代码到构建后代码映射 技术 (如果构建后代码出错,可以通过映射追踪到源代码错误)
格式:[inline- | hidden- | eval-][nosources-][cheap-[module-]]source-map
可以任意排列,但[]的顺序不能乱
具体介绍
source-map: 在外部生成一个文件
在控制台会显示 错误代码准确信息 和 源代码的错误位置
inline-source-map: 内嵌到bundle.js中
只生成一个source-map
在控制台会显示 错误代码准确信息 和 源代码的错误位置
hidden-source-map: 外部
错误代码错误原因,源代码的错误位置
不能追踪源代码错误,只能提示到构建后代码的错误位置
eval-source-map: 内嵌
每一个文件都生成对应的source-map
错误代码准确信息,源代码的错误位置
nosources-source-map: 外部
错误代码准确信息,没有任何源代码信息
cheap-source-map: 外部
错误代码准确信息,源代码的错误位置
只能精准到行
cheap-module-source-map: 外部
错误代码准确信息,源代码的错误位置
module会将loader的source-map加入
内嵌与外部的区别: 1.外部生成单独的文件,内嵌没有 2.内嵌构建速度快
这么多source-map如何选择?
开发环境:速度快,调试更友好
速度快( eval>inline>cheap>··· )
组合eval-cheap-source-map > eval-source-map
调试更友好
source-map > cheap-module-source-map > cheap-source-map
最终结果:cheap-module-source-map 和 eval-source-map (vuecli与react脚手架默认)
生产环境:源代码要不要隐藏?调试要不要更友好
内嵌会让代码体积变大,所以在生产环境下不用内嵌
nosources-source-map全部隐藏
hidden-source-map只隐藏源代码,会提示构建后代码错误信息
最终结果:source-map 和 cheap-module-source-map
*/
runtimeChunk 根据路由驱动页面的 runtime 代码默认情况是包含在 build 后的 app.hash.js 内的,如果我们改动其他路由,就会导致 runtime 代码改变。从而不光我们改动的路由对应的页面 js 会变,含 runtime 代码的 app.hash.js 也会变,对用户体验是非常不友好的。
为了解决这个问题要设定 runtime 代码单独抽取打包;
script-ext-html-webpack-plugin
但是 runtime 代码由于只是驱动不同路由页面的关系,代码量比较少,请求 js 的时间都大于执行时间了,所以使用 script-ext-html-webpack-plugin 插件将其内链在 index.html 中比较友好。所有这两个一般配合使用。
configureWebpack:
optimization: {
runtimeChunk: true
},
plugins: [
new ScriptExtHtmlWebpackPlugin({
inline: /runtime~.+\.js$///正则匹配runtime文件名
})
]
chainWebpack:
config
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [
{
// `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/
}
])
.end()
config.optimization.runtimeChunk('single')
splitChunks
如果使用了某些长期不会改变的库,像 element-ui ,打包完成有 600 多 KB ,包含在默认 vendor 中显然不合适,每次用户都要加载这么大的文件体验不好,所以要单独打包:
chainWebpack:
config.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
commons: {
name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules
minChunks: 3, //minimum common number
priority: 5,
reuseExistingChunk: true
},
libs: {
name: 'chunk-libs',
chunks: 'initial', // only package third parties that are initially dependent
test: /[\\/]node_modules[\\/]/,
priority: 10
},
elementUI: {
name: 'chunk-elementUI',
priority: 20,
test: /[\\/]node_modules[\\/]_?element-ui(.*)/
},
}
})
preload 预加载 提前预加载提高切换路由的体验
config.plugin('preload').tap(() => [
{
rel: 'preload',
fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
【webpack打包优化(vue)】include: 'initial'
}
])
config.plugins.delete('prefetch')
这里要把 runtime 代码的 preload 去掉。
环境配置 .env.production 线上环境打包 // vue-cli-service serve
.env.test测试环境打包 // vue-cli-service test:unit
.env.development 开发环境打包// vue-cli-service build 和 vue-cli-service test:e2eo
.emv.staging 使用mode 打包-- vue-cli-service -- mode staging
.env.local. 本地环境变量,会被 git 忽略上传
环境变量 NODE_ENV、BASE_URL、VUE_APP_开头的变量才能通过 webpacl.DefinePlugin静态的嵌入到客户端的代码中
html-webpack-plugin
会处理 public/index.html 文件。在构建过程中,资源链接会被自动注入。
可以配置多页面入口:
{
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin(),
new HtmlWebpackPlugin({
filename: 'test.html',
template: 'src/assets/test.html'
})
]
}
可以修改默认参数:
Options:{

title:
filename:
.....
}
config导出 导出vue默认webpack设置
vue inspect > output,js

    推荐阅读