# 一、模式和环境变量
# 1、环境变量
我们可以使用process.env
来获取当前系统中定义的所有环境变量。
常见的有:process.env.NODE_ENV、process.env.BASE_URL
NODE_ENV | 当前应用程序所处的环境 | 如 development、production 等。 |
BASE_URL | 生产环境时所在的 URL 的基础路径 | 在 Vue CLI 2 中,BASE_URL 的默认值是 /,在 Vue CLI 3 中,BASE_URL 的默认值是根据 vue.config.js 文件中的 publicPath 选项自动生成的。 |
VUE_APP_* | Vue CLI 中的自定义环境变量 | 在应用程序中可以使用 process.env.VUE_APP_* 来访问这些变量 |
| PUBLIC_URL | 静态资源(如图片、字体等)的基础 URL | Create React App 项目中的一个环境变量 |
那上面的这些环境变量有什么应用场景吗(后面会讲到的)?
# 2、publicPath 值
在 Vue CLI 生成的项目中,如果设置了 publicPath 选项,那么在应用中,可以使用 process.env.BASE_URL
代替 vue router@3 中的 base 选项的值。
// vue router@3中
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
// 静态资源中
<img src="${process.env.BASE_URL}/assets/logo.png" />
并且我们在设置 publicPath 选项时,还可以使用process.env.NODE_ENV
来区分生产环境
publicPath 存在的意义
publicPath 并不是必填项。但当我们的应用程序部署到一个非域名根路径的子路径上时,默认的 绝对路径'/'
会导致项目的路由、静态资源找不到。
module.exports = defineConfig({
// publicPath: '/'
// publicPath: process.env.NODE_ENV === 'production' ? '/my-app/' : '/' // 绝对路径
publicPath: process.env.NODE_ENV === 'production' ? './' : '/' // 相对路径 👏
})
# 3、配置文件
除此之外,我们还可以创建像.env.[NODE_ENV] 类似的文件用于存放不同环境下的环境变量
- .env
开发、生产环境都可以用
VUE_APP_NAME = 'lencamo'
- .env.production
生产环境可用
生产环境中的 VUE_APP_BASE_API 为什么不用加 ip 地址
生产环境下的 VUE_APP_BASE_API 仅仅是一个后端接口标识,Nginx 会利用该标识代理到真正的后端接口地址 https://api.example.com/api
# just a flag
ENV = 'production'
# base api
VUE_APP_BASE_API = /prod-api
应用 1:axios 请求基地址 baseURL
- 环境配置
# .env.development
VUE_APP_BASE_API = /api # 使用项目自身 webpack-dev-serve 的Mock接口
VUE_APP_BASE_API = http://localhost:3000/api # 使用本地后端接口
VUE_APP_BASE_API = https://api.example.com/api # 使用服务器线上接口
# .env.production
VUE_APP_BASE_API = /prod-api # 后端接口标识
- axios 实例
import axios from 'axios'
// 以前
// let BASE_URL = ''
// if (process.env.NODE_ENV === 'production') {
// BASE_URL = 'http://localhost:8080/api'
// } else {
// BASE_RUL = 'http://localhost:8080/api'
// }
// const request = axios.create({
// baseURL: BASE_URL
// // ……
// })
// 现在
const request = axios.create({
baseURL: process.env.VUE_APP_BASE_API
// ……
})
应用 2:devServer 的运行端口 port
// port = 9527 npm run dev OR npm run dev --port = 9527
const port = process.env.port || process.env.npm_config_port || 9527 // dev port
medule.exports = {
devServer: {
port: prot
}
}
# 二、性能优化 ✨
通过npm run serve
运行项目发现其效果类似于 webpack 中的 webpack-dev-server 辅助插件。
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
}
注意:
之前使用 webpack 时,开发环境中打包使用的是dev脚本
而不是serve脚本
性能优化汇总
const TerserPlugin = require('terser-webpack-plugin')
const CompressionWebpackPlugin = require('compression-webpack-plugin')
module.exports = defineConfig({
// dist预览
publicPath: process.env.NODE_ENV === 'development' ? '/' : './',
// 关闭SourceMap
productionSourceMap: false,
chainWebpack: (config) => {
config.when(process.env.NODE_ENV !== 'development', (config) => {
// 图片处理
config.module
.rule('images')
.use('url-loader')
.loader('url-loader')
.tap((options) => {
options.limit = 10 & 1024
return options
})
// 调试代码处理
config.optimization.minimizer('terser').tap((args) => {
args[0].parallel = 4
args[0].terserOptions = {
compress: {
warnings: true,
drop_console: true,
drop_debugger: true
}
}
return args
})
// 打包压缩
config.plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: /\.(js|css)$/,
threshold: 10240,
deleteOriginalAssets: false
// minRatio: 0.8
})
)
})
}
})
# 1、dist 预览
dist 文件项目预览:
不使用 publicPath, 打包的项目必须保证 dist 的内容在服务器的根目录
- vue.config.js
module.exports = defineConfig({
publicPath: process.env.NODE_ENV === 'development' ? '/' : './'
})
# 2、路由懒加载
略
# 3、组件库按需引入
下面摘取几个常用的组件库看看:
# ① element ui
完整引入
- main.js
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
按需引入(手动)✨
先安装:
npm install babel-plugin-component -D
然后配置:
- .babelrc
// 版本 <= CLI2x时
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
- babel.config.js
// 版本 <= CLI2x时
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
]
]
}
最后使用:
通常情况下,按需引入的文件可以单独提取出来,方便管理
- main.js
import './plugins/element.js'
- plugins / element.js
import { Button, Select } from 'element-ui'
Vue.use(Button)
Vue.use(Select)
按需引入(自动)
参考:https://juejin.cn/post/6968448909769179172
vue add element
建议还是使用上面的手动方式,原因如下:
- 安装时,它会更新项目入口文件 App.vue
- 卸载时,不容易成功
# ② vant
略
# 4、关闭 SourceMap
module.exports = defineConfig({
productionSourceMap: false
})
# 5、图片处理
module.exports = defineConfig({
chainWebpack: (config) => {
config.module
.rule('images')
.use('url-loader')
.loader('url-loader')
.tap((options) => Object.assign(options, { limit: 10 * 1024 })) // 10 kb 以下转换为base64
}
})
# 6、CDN 链接 ✍
我们可以通过 CDN 减小包体积,达到性能优化的目的。
更多的 vue-cli 配置可以参考:https://cli.vuejs.org/zh/config/
简单实现
- vue.config.js
const path = require('path')
module.exports = {
configureWebpack: {
// 不需要打包的包
externals: {
qc: 'QC'
}
}
}
- public / index.html
<body>
<!-- built files will be auto injected -->
<!-- 手动引入QC模块 -->
<script
src="http://connect.qq.com/qc_jssdk.js"
data-appid="100556005"
data-redirecturi="http://www.corho.com:8080/#/login/callback"
></script>
</body>
推荐一个免费的 CDN 网站:https://unpkg.com/
unpkg.com/:package@:version/:file
- vue.config.js
代码实现
// 不使用npm安装的包
let externals = {}
// 要使用的第三方CDN包链接
let CDN = { css: [], js: [] }
// 正式配置
if (process.env.NODE_ENV === 'production') {
externals = {
// 基本格式:
// '包名' : '在项目中引入的名字'
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex',
axios: 'axios',
'element-ui': 'ELEMENT' // cdn里的源代码配置💖在ELEMENT这个变量
// (一定要去修改掉引入Element用的变量名, 这里要匹配ELEMENT去替换)
// ……
}
CDN = {
css: [
'https://unpkg.com/[email protected]/lib/theme-chalk/index.css'
// ……
],
js: [
// vue must at first!
'https://unpkg.com/[email protected]/dist/vue.js',
'https://unpkg.com/[email protected]/dist/vue-router.js',
'https://unpkg.com/[email protected]/dist/vuex.js',
'https://unpkg.com/[email protected]/dist/axios.min.js',
'https://unpkg.com/[email protected]/lib/index.js'
// ……
]
}
}
module.exports = defineConfig({
// 需要排除的包对象
configureWebpack: {
externals: externals
},
// 方式1
// 修改原webpack配置(https://webpack.js.org/plugins/html-webpack-plugin/)
chainWebpack: (config) => {
// vue-cli中修改html-webpack-plugin插件(https://cli.vuejs.org/zh/guide/webpack.html#%E4%BF%AE%E6%94%B9%E6%8F%92%E4%BB%B6%E9%80%89%E9%A1%B9)
config.plugin('html').tap((args) => {
args[0].cdn = CDN // 添加新参数
return args
})
},
// 方式2
// 使用vue-cli的page配置(https://cli.vuejs.org/zh/config/#pages)
pages: {
index: {
cdn: CDN // 添加新参数
}
}
})
- public/index.html
代码实现
<head>
<!-- 1、引入CDN的css链接 -->
<% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
<link rel="stylesheet" href="<%=css%>" />
<% } %>
<!-- …… -->
</head>
<body>
<!-- 2、引入CDN的js链接 -->
<!-- built files will be auto injected -->
<% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%=js%>"></script>
<% } %>
<!-- …… -->
</body>
# 7、清除注释/调试代码
先安装:
npm install terser-webpack-plugin -D
然后在 vue.config.js 中进行配置:
const TerserPlugin = require('terser-webpack-plugin') // 去除console.log和debugger语句
module.exports = {
chainWebpack(config) {
config.optimization.minimizer('terser').tap((args) => {
args[0].parallel = 4
args[0].terserOptions = {
compress: {
warnings: true,
drop_console: true, // 删除debugger
drop_debugger: true // 删除console
}
}
return args
})
}
}
# 8、gzip 压缩
提示
当然我们也可以考虑使用服务器端的压缩技术来优化性能,比如 Nginx 服务器可以使用 gzip 压缩技术。
先安装:
npm install compression-webpack-plugin -D
然后在 vue.config.js 中进行配置:
const CompressionWebpackPlugin = require('compression-webpack-plugin') // 开启压缩
module.exports = {
configureWebpack: (config) => {
// 查看打包文件体积大小
config.plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: /\.(js|css)$/, // 匹配需要压缩的文件
threshold: 10240, // 对超过10kb的数据压缩
deleteOriginalAssets: false // 是否删除原文件
// minRatio: 0.8 // 压缩比
})
)
}
}
← vue-cli(上) 【前端架构模式】 →