https://www.cnblogs.com/royal6/p/12988252.html
要首屏优化,首先你要知道有哪些东西可以优化,你可以生成打包报告进行查看。
在package.json中,npm run build
命令中添加如下命令,生成一份报告
根据这份报告,你就知道有哪些文件需要优化了。
一般的优化我们可以在vue.config.js里面优化
configureWebpack
和 chainWebpack
在 vue.config.js 导出的配置对象中,新增 configureWebpack 或 chainWebpack 节点,来自定义 webpack 的打包配置。
在这里, configureWebpack 和 chainWebpack 的作用相同,唯一的区别就是它们修改 webpack 配置的方 式不同:
1.chainWebpack
通过链式编程的形式,来修改默认的 webpack 配置
2.configureWebpack
通过操作对象的形式,来修改默认的 webpack 配置
两者具体的使用差异,可参考如下网址: https://cli.vuejs.org/zh/guide/webpack.html#webpack-相关
接下来就是一些优化的技巧
1.路由懒加载
{
// 首页
path: '/',
name: 'Home',
components: {
default: () => import('@/views/home/index.vue'),
},
meta: { title: '111' }
},
2.关闭预加载模块prefetch(预先加载模块)
因为 vuecli 3默认开启 prefetch(预先加载模块),提前获取用户未来可能会访问的内容
在首屏会把这十几个路由文件,都一口气下载了
所以我们要关闭这个功能,在 vue.config.js中设置
chainWebpack: config => {
config.plugins.delete('preload')
config.plugins.delete('prefetch')
},
3.拆包和组件重复使用打包,当文件的包越来越大的时候,我们需要进行相对应的分包处理,使用异步请求的办法来提升请求的速度。具体的方法如下,还是在webpack配置中
chainWebpack: config => {
config
.when(process.env.NODE_ENV !== 'development',
config => {
config
.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial' // only package third parties that are initially dependent
},
vantUI: {
name: 'chunk-vantUI',
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /vant/ // in order to adapt to cnpm
},
commons: {
name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true
}
}
})
config.optimization.runtimeChunk('single')
}
)
},
我这里拆分的是vant的包和component的包,你也可以按照我的方式拆分其他的包
4.gzip
拆完包之后,我们再用 gzip做一下压缩
在vue.config.js中
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
return {
plugins: [
new CompressionPlugin({
test: /\.js$|\.html$|\.css$/,
// 超过10k才压缩
threshold: 10240,
// 是否删除源文件
deleteOriginalAssets: false
})
// new BundleAnalyzerPlugin()
]
}
}
},
在nginx上的配置如下:
http {
# 开启gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 6;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";
# 设置压缩所需要的缓冲区大小
gzip_buffers 32 4k;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.0;
}
OK,接下来优化的事情就做好了,以下是优化后的结果
完整的vue.config.js配置如下:
const path = require('path')
const CompressionPlugin = require('compression-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin') // 引入删除console插件
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
publicPath: process.env.VUE_APP_BUILD_PATH, // 打包后的文件地址
outputDir: process.env.VUE_APP_FILE_Name, // 打包的文件夹名字
assetsDir: 'static',
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
return {
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
ecma: undefined,
warnings: false, // 传递true以在中返回压缩机警告result.warnings。使用该值可"verbose"获取更详细的警告。
parse: {},
compress: {
drop_console: true, // 移除console
drop_debugger: true, // 移除debugger
pure_funcs: ['console.log'] // 移除console
}
}
})
]
},
plugins: [
new CompressionPlugin({
test: /\.js$|\.html$|\.css$/,
// 超过10k才压缩
threshold: 10240,
// 是否删除源文件
deleteOriginalAssets: false
})
// new BundleAnalyzerPlugin()
]
}
}
},
filenameHashing: true,
// eslint-loader 是否在保存的时候检查
lintOnSave: true,
// 是否使用包含运行时编译器的Vue核心的构建
runtimeCompiler: false,
// 默认情况下 babel-loader 忽略其中的所有文件 node_modules
transpileDependencies: [],
// 生产环境 sourceMap,打包时不生成.map文件 避免看到源码
productionSourceMap: false,
chainWebpack: config => {
config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test
const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
types.forEach(type =>
addStyleResource(config.module.rule('less').oneOf(type))
)
config
.when(process.env.NODE_ENV !== 'development',
config => {
config
.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial' // only package third parties that are initially dependent
},
vantUI: {
name: 'chunk-vantUI',
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /vant/ // in order to adapt to cnpm
},
commons: {
name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true
}
}
})
config.optimization.runtimeChunk('single')
}
)
config.resolve.alias
.set('@', resolve('src'))
.set('imgs', resolve('src/assets/imgs'))
.set('components', resolve('src/components'))
.set('pageComponents', resolve('src/pageComponents'))
.set('http', resolve('src/http'))
.set('utils', resolve('src/utils'))
.set('views', resolve('src/views'))
},
// 配置高于chainWebpack中关于 css loader 的配置
css: {
// 默认情况下,只有 *.module.[ext] 结尾的文件才会被视作 CSS Modules 模块。设置为 false 后你就可以去掉文件名中的 .module 并将所有的 *.(css|scss|sass|less|styl(us)?) 文件视为 CSS Modules 模块。
requireModuleExtension: true,
// 是否使用 css 分离插件 ExtractTextPlugin,采用独立样式文件载入,不采用 <style> 方式内联至 html 文件中 设置为true的话修改样式不会立即生效
extract: false,
// 是否构建样式地图,false 将提高构建速度
sourceMap: false,
loaderOptions: {
less: {
javascriptEnabled: true
}
}
},
devServer: {
open: false, // 运行项目时自动启动浏览器,
port: 777, // 端口号
https: false,
hot: true, // 模块热替换(HMR - hot module replacement)功能会在应用程序运行过程中,替换、添加或删除 模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度
hotOnly: false, // hot 和 hotOnly 的区别是在某些模块不支持热更新的情况下,前者会自动刷新页面,后者不会刷新页面,而是在控制台输出热更新失败
overlay: {
warnings: false, // 当出现编译器错误或警告时,在浏览器中显示全屏覆盖层,如果想要显示警告和错误
errors: true
},
// 设置代理
proxy: {
'/api': {
target: '',
changeOrigin: true,
secure: false, // 如果是https接口,需要配置这个参数
ws: true,
pathRewrite: { // 表示的意思是把/api 替换为空,用在如果你的实际请求地址没有api的情况)
'^/api': ''
}
},
'/foo': {
target: '<other_url>'
}
},
before: app => { }
},
// 构建时开启多进程处理 babel 编译
parallel: require('os').cpus().length > 1,
pwa: {},
// 第三方插件配置
pluginOptions: {}
}
function addStyleResource(rule) {
rule
.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [
path.resolve(__dirname, 'src/assets/css/styles/global.less') // 需要全局导入的less
]
})
}