Vue+express项目优化上线(1)
目录1.Vue项目优化
1.1 项目优化策略
- 生成打包报告
- 第三方库启用CDN
- Element-UI组件按需加载
- 路由懒加载
- 首页内容定制
1.2 通过nprogress添加加载进度条
-
安装运行依赖后,导入并在axios拦截器中使用
-
//设置request拦截器 axios.interceptors.request.use(config => { //展示进度条 Nprogress.start() //为请求头添加一个Authorization的属性,值为sessionStorage中存储的token config.headers.Authorization = window.sessionStorage.getItem('token') return config }) //设置response拦截器 axios.interceptors.response.use(config => { //隐藏进度条 Nprogress.done() return config })
1.3 在发布阶段移除所有console
-
安装babel-plugin-transform-remove-console开发依赖
-
使用方法可参考官方文档
-
babel.config.js文件初步使用
//该文件全局共享,开发阶段和发布阶段都会生效 module.exports = { "presets": [ "@vue/cli-plugin-babel/preset" ], "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ], "transform-remove-console" ] }
- 只在发布阶段移除所有console ```js //这是项目发布阶段要用到的 babel 插件 const prodPlugins = [] //判断当前所处模式 if (process.env.NODE_ENV === 'production') { prodPlugins.push("transform-remove-console") } module.exports = { "presets": [ "@vue/cli-plugin-babel/preset" ], "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ], //发布产品时候的插件数组(...对象展开符) ...prodPlugins ] }
-
1.4 生成打包报告
在打包时生成报告有两种方式:
-
通过命令行参数
//通过 vue-cli 的命令选项可以生成打包报告 // --report 选项可以生成 report.html 以帮助分析包内容 vue-cli-service build --report
-
通过可视化UI面板直接查看
- 控制台 AND 分析
1.5 通过创建vue.config.js修改webpack的默认配置
-
在vue.config.js导出的配置对象中,新增 configureWebpack 或 chainWebpack 节点,来自定义 webpack 的打包配置
-
configureWebpack 和 chainWebpack 的作用相同,唯一区别是它们修改 webpack配置的方式不同
- chainWebpack通过链式编程的形式,来修改默认的webpack配置
- configureWebpack通过操作对象的形式,来修改默认的webpack配置
-
通过chainWebpack自定义打包入口
-
将main.js入口文件复制一份,分别命名main-dev.js&main-prod.js
-
//vue.config.js文件内容 module.exports = { chainWebpack: config => { //发布模式 config.when(process.env.NODE_ENV === 'production', config => { config.entry('app').clear().add('./src/main-prod.js') }) //开发模式 config.when(process.env.NODE_ENV === 'development', config => { config.entry('app').clear().add('./src/main-dev.js') }) } }
-
1.6 通过 externals 加载外部CDN资源
-
默认情况下,通过 import 语法导入的第三方依赖包,最终会被打包合并到一个文件中,导致打包成功后,单文件体积过大问题
-
通过webpack的externals节点,配置并加载外部CDN资源,凡是声明在externals中的第三方依赖包,都不会被打包
-
在 vue.config.js 中进行配置
module.exports = { chainWebpack: config => { //发布模式 config.when(process.env.NODE_ENV === 'production', config => { config. entry('app'). clear(). add('./src/main-prod.js') config.set('externals', { vue: 'Vue', 'vue-router': 'VueRouter', axios: 'axios', echarts: 'echarts', nprogress: 'NProgress', }) }) //开发模式 config.when(process.env.NODE_ENV === 'development', config => { config.entry('app').clear().add('./src/main-dev.js') }) } }
-
在index.html文件中导入CDN资源
<head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title><%= htmlWebpackPlugin.options.isProd ? '' : 'dev - ' %>522人事工资管理后台网站</title> <% if(htmlWebpackPlugin.options.isProd){ %> <!--nprogress的样式表文件--> <link href="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css" rel="stylesheet"> <!--element-ui的样式表--> <link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.9.0/theme-chalk/index.css" rel="stylesheet"> <!--js文件--> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.2.0/vue-router.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.9.0-rc.1/echarts.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0/axios.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.9.0/index.js"></script> <% } %> </head>
-
优化后进行打包,js文件大小减少了大半,警告减少了一个
-
此处遇坑:即使使用了项目依赖对应版本的element-ui的cdn,打包后显示也不正常,切换多个版本后解决
1.7 首页内容定制
-
不同的打包环境下,首页内容可能会有所不同,我们可以通过插件的方式进行定制
-
在开发与发布环境中为isProd设置不同的值
//为html插件新增自定义属性isProd config.plugin('html').tap(args => { args[0].isProd = true return args })
-
在index.html中根据isProd展示不同内容
<head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title><%= htmlWebpackPlugin.options.isProd ? '' : 'dev - ' %>title</title> <% if(htmlWebpackPlugin.options.isProd){ %> <!--nprogress的样式表文件--> <link href="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css" rel="stylesheet"> <!--element-ui的样式表--> <link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.4.5/theme-chalk/index.css" rel="stylesheet"> <!--js文件--> <script src="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.2.0/vue-router.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.9.0-rc.1/echarts.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0/axios.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.4.5/index.js"></script> <% } %> </head>
1.8 路由懒加载
-
打包项目时,js包巨大,影响页面加载,可以把不同路由对应组件分割成不同的代码块,当路由被访问时才加载对应组件,提升效率
-
安装@babel/plugin-syntax-dynamic-import开发依赖
-
配置在babel.config.js文件中
-
改造router/index.js文件
import Vue from 'vue' import VueRouter from 'vue-router' /* import Login from "@/views/Login"; import Home from "@/views/Home"; import Welcome from "@/views/Welcome"; import Users from "@/views/user/users"; import Rights from "@/views/power/Rights"; import Roles from "@/views/power/Roles"; import Positions from "@/views/staff/Positions"; import Staffs from "@/views/staff/Staffs"; import Events from "@/views/event/Events"; import Attendance from "@/views/staff/Attendance"; import Reports from "@/views/report/Reports"; */ //路由懒加载 const Login = () => import(/* webpackChunkName: "login_home_welcome" */ '../views/Login') const Home = () => import(/* webpackChunkName: "login_home_welcome" */ '../views/Home') const Welcome = () => import(/* webpackChunkName: "login_home_welcome" */ '../views/Welcome') const Users = () => import(/* webpackChunkName: "users_rights_roles" */ '../views/user/Users') const Rights = () => import(/* webpackChunkName: "users_rights_roles" */ '../views/power/Rights') const Roles = () => import(/* webpackChunkName: "users_rights_roles" */ '../views/power/Roles') const Attendance = () => import(/* webpackChunkName: "attendance_positions_staffs" */ '../views/staff/Attendance') const Positions = () => import(/* webpackChunkName: "attendance_positions_staffs" */ '../views/staff/Positions') const Staffs = () => import(/* webpackChunkName: "attendance_positions_staffs" */ '../views/staff/Staffs') const Events = () => import(/* webpackChunkName: "events" */ '../views/event/Events') const Reports = () => import(/* webpackChunkName: "reports" */ '../views/report/Reports') Vue.use(VueRouter) const routes = [ { path: '/', redirect: '/login'},//访问根路径时重定向到:/login { path: '/login', component: Login }, { path: '/home', component: Home, redirect: '/welcome', children: [ { path: '/welcome', component: Welcome }, { path: '/users', component: Users }, { path: '/rights', component: Rights }, { path: '/roles', component: Roles }, { path: '/positions', component: Positions }, { path: '/staffs', component: Staffs }, { path: '/events', component: Events }, { path: '/attendance', component: Attendance }, { path: '/reports', component: Reports } ]} ] const router = new VueRouter({ routes }) export default router
-
优化后js大文件被分割成数个小文件