介绍
关于Vue3 和 Vue cil4的打包记录
# 关于Vue3 和 Vue cil4的打包
- 主要记录的是Vue3和Vue cil4的打包内容 用于优化项目的打包占比
- 有关的配置文件为
vue.config.js
# 生成Vue打包文件的大小占比
build
后我们可以详细查看那些组件占用的大小
第一步 npm下载插件
npm install webpack-bundle-analyzer --save-dev
第二步 在
vue.config.js
中配置
chainWebpack: config => {
// 查看打包文件体积大小
config
.plugin('webpack-bundle-analyzer')
.use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
}
第三步 在
package.json
文件中的 build 后面加上一个--report
"build": "vue-cli-service build --report",
第四步 进行build打包
- 运行
npm run build
后他会打包 并且打包完毕后 自动打开打包占比页面 让你详细了解打包的占比
# 使用gzip
或者Brotli
压缩算法
- webpack默认打包是js的压缩 我们可以再在技术上进行压缩处理
- 注意: 使用
gzip
和Brotli
需要后端进行配置 否则不可以使用
下载webpack压缩功能
- 注意版本 Vue cli4不能使用高版本的压缩 否则会报错
npm i compression-webpack-plugin@6.1.0 -D
- 使用
-D
在服务器(开发依赖中)devDependencies
使用 -S
会把依赖包安装到node_modules
目录中 本地也会使用
# 使用gzip
压缩算法
gzip
的压缩方式- 注意: 注意奥 修改的是
vue.config.js
文件 每次修改这文件都需要重启项目
// 引入压缩插件
const CompressionPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i // 开启gzip压缩类型
module.exports = {
configureWebpack: {
// 配置压缩
plugins: [
new CompressionPlugin({
/* [file]被替换为原始资产文件名。
[path]替换为原始资产的路径。
[dir]替换为原始资产的目录。
[name]被替换为原始资产的文件名。
[ext]替换为原始资产的扩展名。
[query]被查询替换。*/
filename: '[path].gz[query]',
//压缩算法
algorithm: 'gzip',
//匹配文件
test: productionGzipExtensions,
//压缩超过此大小的文件,以字节为单位
threshold: 10240,
minRatio: 0.8,
//删除原始文件只保留压缩后的文件
deleteOriginalAssets: true
})
]
}
}
# 使用Brotli
压缩算法
- Brotli (opens new window)是最初由Google开发的一种压缩算法,其压缩性能优于gzip。node11.7.0及更高版本在其zlib模块中具有对Brotli压缩的支持,相对gzip压缩提高20%。
const CompressionPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i // 开启Brotli压缩类型
module.exports = {
//设置为false以加速生产环境构建(非必须)
productionSourceMap: false,
configureWebpack: {
plugins: [
new CompressionPlugin({
filename: "[path].br[query]",
algorithm: "brotliCompress",
test: productionGzipExtensions,
compressionOptions: { level: 11 },
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: true
})
]
}
}
# 修改页面title
- 默认我们创建Vue Cil的时候 title默认是你项目名称
- 我们想实现上面通过路由名称的高度定制的title
# 实现思路
实现灵活自定义title 有两种方式
- 第一种 在
vue.config.js
配置文件中的chainWebpack
设置title 但是这种title是固定的 不是根据路由名称而变化的 - 第二种 在
router
路由配置文件中 使用router.beforeEach
这样他会根据你路由的title
属性 来生成相应的title名称
- 第一种 在
我们知道这两种方式后还需要修改
index.html
把他的title设置成灵活配置的title
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
- 知道实现的思路 我们可以让两者结合使用 如果你只通过
router.beforeEach
设置默认title 那么页面刚打开的时候 不会生效 效果会不好 所以他俩结合使用- 用户刚进入页面的时候 显示
vue.config.js
配置的默认title 通常是项目名称
- 等页面加载完毕后 会自动替换成
router.beforeEach
设置的路由title 通常是当前项目页面的名称
( 当然你可以都设置同样的名称 )
- 用户刚进入页面的时候 显示
# 具体操作
- 设置
vue.config.js
配置的默认title 然后通过Vue router中的router.beforeEach
设置的路由title
第一步 配置的默认title
- 设置
vue.config.js
配置的默认title
const name = '我是默认标题'
chainWebpack: config => {
// 设置默认的标题名称 配合 路由beforeEach 默认不设置的话是项目名字
config.plugin('html').tap(args => {
args[0].title = name
return args
})
}
第二步 设置的路由title
- 设置
router.beforeEach
设置的路由title 如果不设置 默认就是使用vue.config.js
的配置
// 路由的title
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue'),
meta: {
title: '我是默认标题_首页'
}
}
// 设置路由title
router.beforeEach((to, from, next) => {
document.title = to.meta.title
next()
})
# 拼接默认title和路由title
- 按照以上方式设置路由title会出现一个问题 我们在
vue.config.js
设置的默认title 等Vue加载完毕后会被Vue router的路由title替换掉 - 我们想让
vue.config.js
设置的默认title 和 路由title 拼接起来一起显示
第一步 新建一个CommonJS 导出方式的js配置文件 设置默认标题
- 在Vue cil4中
vue.config.js
不支持es6import
的导出方式 只能通过CommonJS的module.exports
模块化导出方式
// 设置通用的配置文件 settings.js
module.exports = {
// 配置默认title
title: '学习three.js'
}
第二步 在
vue.config.js
导入使用
- 通过
require()
模块化导入 使用配置的文件中的默认title
// 导入通用提示
const defaultSettings = require('./src/settings')
// 使用配置标题
const name = defaultSettings.title
chainWebpack: config => {
// 设置默认的标题名称 配合 路由beforeEach 默认不设置的话是项目名字
config.plugin('html').tap(args => {
args[0].title = name
return args
})
}
第三步 在Vue router配置拼接
- 在Vue router的配置文件中 进行拼接操作 把路由title 和 默认title 拼接起来一起显示
// 导入通用提示
const defaultSettings = require('@/settings')
// 设置路由title
router.beforeEach((to, from, next) => {
// 把路由title 和 默认title拼接起来
document.title = `${to.meta.title} - ${defaultSettings.title} `
next()
})
# 创建生开发环境.env
- 我们开发的除本地以外 还分为 测试环境(qa) 和 正式环境
- 通常我们开发的时候 api根路径会根据测试还是生产来修改 每次手动修改的话费时费力 还容易操作失误 那我们可以通过创建
.env
环境文件 来告诉package.json
我们的打包 是否在测试还是生产 - 我们可以再任何一个js文件中 来进行开发生产环境的判断
process.env.环境依据 === '环境依据参数'
了解脚手架的环境默认命名规范
development
模式用于vue-cli-service serve
(本地环境)test
模式用于vue-cli-service test:unit
(测试环境)production
模式用于vue-cli-service build
和vue-cli-service test:e2e
(正式环境)
第一步 创建一个
.env
环境文件
- 这里我们可以直接声明一个变量(无需 let const) 这个时候
NODE_ENV
就可以作为环境的判断 #
是注释
# 环境依据 我们打包的时候 可以以他为依据来判断 我们直接创建一个正式环境
NODE_ENV = 'production'
# 节点路径 根路径
VUE_APP_BASE_API = 'https://miningrenewapi.lshmnc.com.cn/public/'
- 创建路径
第二步 在
package.json
中注册
- 创好了
.env
环境文件 我们还需要注册 - 你可以创建多个
.env
环境文件 配置都是一样的
"scripts": {
"dev": "vue-cli-service serve",
"build:master": "vue-cli-service build --mode production",
"lint": "vue-cli-service lint"
},
- 我们想让
npm run build:master
的时候使用生产环境 (当然你可以创建其他指令) 就需要绑定--mode 环境文件名
第三步 在axios 中灵活使用根路径
- 我们开发肯定分为测试和生产 那么接口的根路径来回去修改很麻烦 我们可以让其灵活替换 就是用到我们的
.env
环境文件 - 什么文件也不需要导入 他会自动根据你
package.json
的指令来灵活替换环境文件的根路径配置
// 请求的基准路径 常量保存并且支持导出 通过process.env调用
const baseURL = process.env.VUE_APP_BASE_API
// 创建独立的axios的实例
const instance = axios.create({
// baseURL是axios属性 用来声明url基础路径(比对上面声明的常量)
baseURL: baseURL
// 设置响应超时 建议不设置 或者设置时间较长 会影响一些较大的文件下载
// timeout: 5000
})
第四步 在
vue.config.js
中进行生产判断
- 打包的时候 有些数据需要特殊处理 比如CDN加速 等等... 这个时候我们要在
vue.config.js
进行配置防止影响到测试或者本地环境
// 判断是否是生产环境
const isProduction = process.env.NODE_ENV === 'production'
module.exports = {
chainWebpack: config => {
if (isProduction) {
// 生产环境的处理
}else{
// 测试和本地环境的处理
}
}
}
常用的开发环境合集
development // 测试
production // 生产
test // 功能测试
# 移除console.log打印
- 做项目的时候 经常会用到
console.log
我们打包到生产环境的时候 不想显示 这个时候就需要特殊处理 - 注意: 这个不需要判断是否是在本地环境还是生产或测试环境 本地环境不会触发 只有
build
打包的生产和测试环境才会触发 删除console.log
下载webpack移除功能
- 注意版本 Vue cli4不能使用高版本的移除 否则会报错
npm install terser-webpack-plugin@4.2.3 --save-dev
# 移除操作
- 注意: 注意奥 修改的是
vue.config.js
文件 每次修改这文件都需要重启项目 - 遇到了一个问题 Vue3 + Vue cil4 打包速度会变慢 不知道为什么
// 导入去除console
const TerserPlugin = require('terser-webpack-plugin')
configureWebpack: {
// ... 无关的内容
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
ecma: undefined,
warnings: false,
parse: {},
compress: {
drop_console: true,
drop_debugger: false, // 默认false,设置为true, 则会删除所有console.* 相关的代码。
pure_funcs: ['console.log'] // 移除console
}
}
})
]
}
},
# 按需导入elementPlus
elementPlus
可以通过Vue3的打包插件 实现按需打包 详情官方教程 (opens new window)
第一步 安装自动打包插件
- 首先你需要安装
unplugin-vue-components
和unplugin-auto-import
这两款插件
npm install -D unplugin-vue-components unplugin-auto-import
第二步 在
vue.config.js
中使用
// webpack.config.js
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = {
configureWebpack: {
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
],
}
}
- 注意: 如果你之前用的是全局导入 你需要在
main.js
入口文件中去掉elementPlus
的导入
# 其他的vue.config.js的配置项
- 基于Vue cli4的其他配置项
const path = require('path')
const CompressionWebpackPlugin = require('compression-webpack-plugin') // 开启gzip压缩, 按需引用
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i // 开启gzip压缩, 按需写入
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin // 打包分析
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
const resolve = (dir) => path.join(__dirname, dir)
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '/site/vue-demo/' : '/', // 公共路径
indexPath: 'index.html', // 相对于打包路径index.html的路径
outputDir: process.env.outputDir || 'dist', // 'dist', 生产环境构建文件的目录
assetsDir: 'static', // 相对于outputDir的静态资源(js、css、img、fonts)目录
lintOnSave: false, // 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码
runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
productionSourceMap: !IS_PROD, // 生产环境的 source map
parallel: require('os').cpus().length > 1, // 是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。
pwa: {}, // 向 PWA 插件传递选项。
chainWebpack: config => {
config.resolve.symlinks(true) // 修复热更新失效
// 如果使用多页面打包,使用vue inspect --plugins查看html是否在结果数组中
config.plugin('html').tap(args => {
// 修复 Lazy loading routes Error
args[0].chunksSortMode = 'none'
return args
})
config.resolve.alias // 添加别名
.set('@', resolve('src'))
.set('@assets', resolve('src/assets'))
.set('@components', resolve('src/components'))
.set('@views', resolve('src/views'))
.set('@store', resolve('src/store'))
// 压缩图片
// 需要 npm i -D image-webpack-loader
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
mozjpeg: { progressive: true, quality: 65 },
optipng: { enabled: false },
pngquant: { quality: [0.65, 0.9], speed: 4 },
gifsicle: { interlaced: false },
webp: { quality: 75 }
})
// 打包分析, 打包之后自动生成一个名叫report.html文件(可忽视)
if (IS_PROD) {
config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
{
analyzerMode: 'static'
}
])
}
},
configureWebpack: config => {
// 开启 gzip 压缩
// 需要 npm i -D compression-webpack-plugin
const plugins = []
if (IS_PROD) {
plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: productionGzipExtensions,
threshold: 10240,
minRatio: 0.8
})
)
}
config.plugins = [...config.plugins, ...plugins]
},
css: {
extract: IS_PROD,
requireModuleExtension: false, // 去掉文件名中的 .module
loaderOptions: {
// 给 less-loader 传递 Less.js 相关选项
less: {
// `globalVars` 定义全局对象,可加入全局变量
globalVars: {
primary: '#333'
}
}
}
},
devServer: {
overlay: { // 让浏览器 overlay 同时显示警告和错误
warnings: true,
errors: true
},
host: 'localhost',
port: 8080, // 端口号
https: false, // https:{type:Boolean}
open: false, // 配置自动启动浏览器
hotOnly: true, // 热更新
// proxy: 'http://localhost:8080' // 配置跨域处理,只有一个代理
proxy: { // 配置多个跨域
'/api': {
target: 'http://172.11.11.11:7071',
changeOrigin: true,
// ws: true,//websocket支持
secure: false,
pathRewrite: {
'^/api': '/'
}
},
'/api2': {
target: 'http://172.12.12.12:2018',
changeOrigin: true,
// ws: true,//websocket支持
secure: false,
pathRewrite: {
'^/api2': '/'
}
}
}
}
}
# 使用CDN 把较大组件进行加速
- 我不会 学了半天没整明白
# vue cli5自动打开问题
- vue cli5
devServer
中的open
本地直接打开项目的方法有bug 会打开地址为http://0.0.0.0:8080
而非http://localhost:8080
使得页面无法打开
解决方案
port
设置指定端口后 指定open
本地直接打开的页面路径
devServer: {
// 开启的端口名称
port: 8888,
// 本地直接打开的页面路径
open: 'http://localhost:8888'
},