面临情况
在没有缓存的情况下,浏览器第一次加载要8~9秒
打出来的包比较大,全文件夹下来18.7M
1、先去掉map文件,设置了不要map文件还是这样会打出来,好奇怪
productionSourceMap: false, // 是否要map文件
发现是这个配置影响了
module.exports = {
configureWebpack: () => ({
devtool: 'source-map',
}),
}
- 这个属性的官方解释 webpack官网
1、使用 SourceMapDevToolPlugin 进行更细粒度的配置。查看 source-map-loader 来处理已有的 source map。
2、选择一种 source map 格式来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。
注释devtool: 'source-map’后打出来的包反而变大了,全文件夹下来22.2M
改为eval,打包后全文件下来11M
module.exports = {
configureWebpack: () => ({
devtool: 'eval',
}),
}
包实在是太大了,估计是引入某个包太大了,猜测要么是拼音,要么是语音输入,找了一圈,最后发现是echart太大了
2、引入echart的CDN,参考了博客vue-cli4项目配置cdn引入静态资源
按照配置修改后我的页面报错了
3、搞不定,还是看官网吧vue-cli官网
configureWebpack
-
如果这个值是一个对象,则会通过 webpack-merge 合并到最终的配置中。
-
如果这个值是一个函数,则会接收被解析的配置作为参数。该函数既可以修改配置并不返回任何东西,也可以返回一个被克隆或合并过的配置版本。
1、我这里是以对象的方式配置的,官方文档的意思是,如果你要判断是生产环境还是开发环境,你就使用函数的方式,不区分就使用对象的方式
2、外部扩展externals
防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。例如,从 CDN 引入 jQuery,而不是把它打包
// 配置webpack
configureWebpack: {
devtool: 'eval',
resolve: {
// 配置项目别名
alias: {
'assets': path.resolve('./src/assets'),
'api': path.resolve('./src/api'),
'components': path.resolve('./src/components'),
'utils': path.resolve('./src/utils'),
'views': path.resolve('./src/views'),
'styles': path.resolve('./src/styles'),
'@': resolve('src')
}
},
externals: {
vue: 'Vue',
axios: 'axios',
'vant': 'VANT',
'echarts': 'echarts',
'vue-router': 'VueRouter',
vuex: 'Vuex',
'element-ui': 'ELEMENT'
},
},
4、vue-cli的pages
在 multi-page 模式下构建应用。每个“page”应该有一个对应的 JavaScript 入口文件。其值应该是一个对象,对象的 key 是入口的名字,value 是:
一个指定了 entry, template, filename, title 和 chunks 的对象 (除了 entry 之外都是可选的);
或一个指定其 entry 的字符串。
pages: {
index: {
entry: 'src/main.js',
template: 'public/index.html',
filename: 'index.html',
chunks: ['chunk-vendors', 'chunk-common', 'index'],
cdn: {
css: [
'https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/theme-chalk/index.css'
],
js: [
"https://cdn.staticfile.org/vue/2.5.22/vue.min.js",
"https://cdn.staticfile.org/vue-router/3.0.2/vue-router.min.js",
"https://cdn.staticfile.org/axios/0.19.0-beta.1/axios.min.js",
'https://cdn.jsdelivr.net/npm/vant@1.6/lib/vant.min.js',
"https://cdn.staticfile.org/vuex/3.1.1/vuex.min.js",
"https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/index.js",
"https://cdn.bootcss.com/echarts/4.8.0/echarts.simple.min.js",
]
},
}
},
配置完pages后要配置index.html,用asp语句动态动态生产secript标签和link标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- 适配iPhone X viewport-fit=cover -->
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover" />
<meta name="format-detection" content="telephone=yes" />
<link rel="icon" href="<%= BASE_URL %>app_logo.svg" />
<% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
<link href="<%=js%>" rel="preload" as="script" />
<script src="<%=js%>"></script>
<% } %>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<title></title>
</head>
<body>
<noscript>
<strong>We're sorry but vue-cli3-project doesn't work properly without
JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
</body>
</html>
配置cdn后,打包后的文件显著减小
bootcnd
5、遇到问题,从cdn引入axios,在main.js中把axios挂在原型中,在别的文件中以this.$axios配置axios会不生效
// import axios from "axios"
Vue.prototype.$axios = axios
在Staff-login.js就算按下面的设置了,请求还是么得token,搞不定,axios还是不导入cdn了
this.$axios.defaults.headers.common['token'] = this.queryData.token
6、包还是很大,查看分析
- 先装上分析插件 webpack-bundle-analyzer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin // 导入
module.exports = {
configureWebpack:{
// 配置
plugins:[
new BundleAnalyzerPlugin({ analyzerPort: 8919 })
]
}
}
打包后会自动出现一个端口为8919的站点,站点内容如下:
chainWebpack 是一个函数,会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。
7、配置优化,拆包
module.exports = {
configureWebpack:{
// 优化
//优化
optimization: {
//告知 webpack 使用 TerserPlugin 或其它在 optimization.minimizer 定义的插件压缩 bundle。
minimize: true,
// 对于动态导入模块,默认使用 webpack v4+ 提供的全新的通用分块策略
splitChunks: {
chunks: 'async',
minSize: 30000,
// minRemainingSize: 0,//这个打开会报错
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 6,
maxInitialRequests: 4,
automaticNameDelimiter: '~',
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
}
}
加上这个后又小了一些,总共10.3
8、剩下比较大的svg和vconsole,按理说vconsole是不需要在生产用的
- vsonsole忘了注释掉了,注释掉就不会打包进来了,或者可以配置vconsole只在生产展示
// import Vconsole from "vconsole"
// const vConsole = new Vconsole()
// Vue.use(vConsole)
- svg好解决,删掉不要的就行
结果,从最开始的18.7M到最后的3.36M,感觉包的大小还是优化了蛮多的,加载时间也从8s多到现在1s左右
最后贴上vue.config.js,
const CompressionPlugin = require('compression-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
// 自动增加浏览器前缀,提高兼容性
const autoprefixer = require('autoprefixer')
const path = require('path')
const resolve = dir => path.join(__dirname, dir)
const IS_PROD = process.env.NODE_ENV === 'production'
const cdnDomain = '/'
module.exports = {
publicPath: IS_PROD ? cdnDomain : '/',
productionSourceMap: false, // 是否要map文件
lintOnSave: false, //设置是否在开发环境下每次保存代码时都启用 eslint验证。
devServer: {
hot: true,
// 设置端口
port: 9527,
https: false,
hotOnly: false,
overlay: {
warnings: true,
errors: true
},
// 配置多个代理
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: process.env.BASE_URL,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
}
}
},
chainWebpack: config => {
const svgRule = config.module.rule('svg') // 找到svg-loader
svgRule.uses.clear() // 清除已有的loader, 如果不这样做会添加在此loader之后
svgRule.exclude.add(/node_modules/) // 正则匹配排除node_modules目录
svgRule // 添加 svg新的 loader 处理
.test(/\.svg$/)
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
// 修改images loader 添加svg处理
const imagesRule = config.module.rule('images')
imagesRule.exclude.add(path.resolve('src/assets/icons'))
// 图片压缩
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
.use('img-loader')
.loader('img-loader').options({
plugins: [
require('imagemin-jpegtran')(),
require('imagemin-pngquant')({
quality: [0.75, 0.85]
})
]
})
// 启用GZip压缩
config
.plugin('compression')
.use(CompressionPlugin, {
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'),
threshold: 10240,
minRatio: 0.8,
cache: true
})
.tap(args => { })
},
css: {
loaderOptions: {
postcss: {
plugins: [
autoprefixer(),
// 使用px-to-viewport做屏幕适配
require('postcss-px-to-viewport')({
unitToConvert: 'px',
viewportWidth: 375, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750
viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置
unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数
viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw
selectorBlackList: [], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false // 允许在媒体查询中转换`px`
})
]
},
less: {
modifyVars: {
black: '#313131',
red: '#F44',
blue: '#666666',
orange: '#F89516',
green: '#268AED',
'text-color': '#313131',
'background-color': '#F5F5F5',
// 按钮重置
'button-default-height': '38px',
'button-default-line-height': '36px',
'button-default-font-size': '14px',
'button-default-color': '#34394A',
'button-default-border-color': '#DDD',
'button-large-height': '47px',
'button-large-line-height': '45px',
'button-border-radius': '4px',
'button-small-font-size': '14px',
'button-small-min-width': '64px',
// nav重置
'nav-bar-arrow-size': '18px',
'nav-bar-title-font-size': '17px'
}
}
}
},
// 配置webpack
configureWebpack: {
// devtool: 'eval',
devtool: 'source-map',
resolve: {
// 配置项目别名
alias: {
'assets': path.resolve('./src/assets'),
'api': path.resolve('./src/api'),
'components': path.resolve('./src/components'),
'utils': path.resolve('./src/utils'),
'views': path.resolve('./src/views'),
'styles': path.resolve('./src/styles'),
'@': resolve('src')
}
},
externals: {
vue: 'Vue',
// axios: 'axios',// 不能用cdn,不然配置没法用,暂未找到原因
'vant': 'VANT',
'echarts': 'echarts',
'vue-router': 'VueRouter',
vuex: 'Vuex',
// swiper: 'swiper', // cdn加载太慢
// "vue-ls": "vue-ls", // cdn加载太慢
'lottie-web': 'lottie-web',
'element-ui': 'ELEMENT'
},
plugins: [
// 分析打包体积
new BundleAnalyzerPlugin({ analyzerPort: 8919 })
],
//优化
optimization: {
//告知 webpack 使用 TerserPlugin 或其它在 optimization.minimizer 定义的插件压缩 bundle。
minimize: true,
// 对于动态导入模块,默认使用 webpack v4+ 提供的全新的通用分块策略
splitChunks: {
chunks: 'async',
minSize: 30000,
// minRemainingSize: 0,//webpack官网搂过来的,但是有这句会报错
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 6,
maxInitialRequests: 4,
automaticNameDelimiter: '~',
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
},
pages: {
index: {
entry: 'src/main.js',
template: 'public/index.html',
filename: 'index.html',
chunks: ['chunk-vendors', 'chunk-common', 'index'],
// 配置在index.html动态生成的标签
cdn: {
css: [
'https://cdn.jsdelivr.net/npm/vant@2.2/lib/index.css'
],
js: [
"https://cdn.staticfile.org/vue/2.5.22/vue.min.js",
"https://cdn.staticfile.org/vue-router/3.0.2/vue-router.min.js",
// "https://cdn.staticfile.org/axios/0.19.0-beta.1/axios.min.js",// 不能用cdn,不然配置没法用,暂未找到原因
'https://cdn.jsdelivr.net/npm/vant@1.6/lib/vant.min.js',
"https://cdn.staticfile.org/vuex/3.1.1/vuex.min.js",
"https://cdn.jsdelivr.net/npm/element-ui@2.13.2/lib/index.js",
"https://cdn.bootcss.com/echarts/4.8.0/echarts.simple.min.js",
"https://cdn.staticfile.org/lottie-web/5.7.1/lottie.min.js",
// "https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.0.2/js/swiper.min.js",// cdn加载太慢
// "https://cdn.bootcdn.net/ajax/libs/vue-ls/3.2.1/vue-ls.js",// cdn加载太慢
]
},
}
}
}