项目架构与优化
package.json基本命令配置
js
"scripts": {
"dev": "vue-cli-service serve", // 开发
"build": "vue-cli-service build", // 打包
"lint": "vue-cli-service lint", // 检查 .eslintrc.js 文件配置项
"report": "vue-cli-service build --report" // 打包并生成分析报告
}
一、ESlint + .editorconfig + .gitattributes 统一编程规范
- 参考项目根目录 .eslintrc.js + .editorconfig + .gitattributes
二、scss全局mixins常用css变量、布局
- 参考assets/style目录: scss全局配置
css
/* mixin.scss */
@mixin child-center {
display: flex;
justify-content: center;
align-items: center;
}
/* variable.scss */
$f-color:#000;
$f-size: 16px;
$safe-color: #00FF99;
三、抽离基本库(如:Vue、VueRouter、Vuex、axios、第三方UI库),部署CDN访问
js
// vue.config.js
const cdn = require('./cdn.config.js')
// ...
pages: {
index: {
entry: 'src/main.js',
title: 'vue-cli-framework',
cdn // cdn注入方式1
}
},
chainWebpack: (config) => {
// 生产&开发 环境忽略的打包文件,如需判断,使用 process.env.NODE_ENV
// *格式: '引入的包名': 'cdn引入的全局变量名称'
// *key:value请严格核对,否则影响站点加载全局变量导致白屏
config.externals({
'vue': 'Vue',
'vuex': 'Vuex',
'vue-router': 'VueRouter',
'axios': 'axios',
'element-ui': 'ELEMENT',
})
},
chainWebpack: (config) => {
// cdn注入方式 2
// config
// .plugin('html-index')
// .tap((args) => {
// args[0].cdn = cdn
// return args
// })
}
html
// public/index.html
<head>
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- 不能使用相对路径,否则无法访问到favicon.ico或者loading.css -->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- CDN注入css -->
<% for (var i of htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
<link rel="stylesheet" href="<%=[i] %>" preload>
<% } %>
<style>
/* 居中loading */
.temp-loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div id="app">
<img src="./svg/loading.svg" class="temp-loading" alt="加载中,请稍后..." title="加载中,请稍后...">
</div>
<!-- CDN注入, ejs模板语法 -->
<% for (var i of htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%=[i] %>" preload></script>
<% } %>
<img src="./test.jpg" alt="">
</body>
注意
配置cdn访问后,禁止Element配置按需加载,否则会将Element打包
Element需引入css与js
四、因浏览器请求并发限制,建议适当禁用小模块懒加载(合并打包),实现一次请求
js
// 小模块使用相同 webpackChunkName
const routes = [
{
path: '/',
name: 'Home',
component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "Home" */ '../views/about.vue')
}
]
五、执行RESTful API标准开发, axios封装约定API状态码
六、Nginx启用Gzip(兼容所有http(s)) + Brotli(兼容https(IE不支持))压缩,前端负责构建压缩文件,减轻服务器开销
- Gzip开启较为容易(速度提升80%)
- Brotli开启有点麻烦(暂未研究,较Gzip提升20%)
前端构建配置
- vue add vue-cli-plugin-compression
js
// vue add 添加的插件,插件可通过 `options.pluginOptions.key` 访问这些选项
pluginOptions: {
// 具备默认配置,可不配置
compression: {
// br压缩
brotli: {
filename: '[path].br[query]', // path: 文件完整路径 query: 文件query
algorithm: 'brotliCompress', // 压缩算法
include: /\.(js|css|html|svg|json)(\?.*)?$/i, // 匹配文件
threshold: 1024 * 150, // 单位字节:只压缩150kb的资源
deleteOriginalAssets: false // 删除源文件
},
// gzip压缩
gzip: {
filename: '[path].gz[query]',
algorithm: 'gzip',
include: /\.(js|css|html|svg|json)(\?.*)?$/i,
threshold: 1024 * 150,
deleteOriginalAssets: false
}
}
}
TIP
- Gzip默认会压缩svg,与图片压缩loader可能会存在冲突,因此择一处理svg即可。
七、图片压缩
- cnpm i -D vue-cli-plugin-compression
js
// 默认配置的插件配置更改, 查看插件名称:vue inspect --plugins
chainWebpack: (config) => {
config.module.rule('images')
.test(/\.(png|jpe?g|gif)(\?.*)?$/) // svg 放到svg-sprite-loader处理
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
bypassOnDebug: true
})
},
注意
- 如果:Cannot find module 'imagemin-gifsicle', 使用cnpm装该依赖
八、开启http2
js
// nginx轻松配置
server {
listen 443 ssl http2; // listen中声明即可
}
九、集群/Docker部署 + Nginx负载均衡 + Jenkins持续集成,实现前端无感知发布【后端支持】
- 负载均衡测试文档, 暂未深入研究
svg精灵图
见项目
路由权限控制
其他
动画性能优化
- 在 CSS 中,transforms 和 opacity 这两个属性更改不会触发重排与重绘,它们是可以由合成器(composite)单独处理的属性。