组件划分
- 功能型组件
- UI 组件库
- 业务型组件
- 通用组件 components
- 普通业务组件
项目优化的策略
- 生成打包报告
- 第三方库启用 CDN
- Element-ui 组件按需加载
- 路由懒加载
- 首页内容定制
进度条使用
当数据加载慢的时候,可以展示出一个进度条
npm install --save nprogress
在 main.js 文件中导入 js 文件与 css 文件
// 导入NProgress包和css
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
在发送请求的时候开启进度条,在获取响应后关闭进度条
// 在request拦截器中,展示进度条NProgress.start()
axios.interceptors.request.use((config) => {
NProgress.start()
config.header.Authoriztion = window.sessionStorage.getItem('token')
return config
})
// 在response拦截器隐藏进度条 NProgress.done()
axios.interceptors.response.use((config) => {
NProgress.done()
return config
})
移除 console.log 指令
在项目开发的时候,我们为了测试,写了很多的 console.log 输出打印,但是当项目发布的时候,就应该将这些内容删除掉
通过 babel-plugin-transform-remove-console 包来完成
npm install babel-plugin-transform-remove-console --save-dev
在项目根目录下找到 babel.config.js 文件,做如下配置
const prodPlugins = []
if (process.env.NODE_Env === 'production') {
prodPlugins.push('transform-remove-console')
}
module.exports = {
presets: ['@vue/app'],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk',
},
],
// 发布产品时候的插件数组
...prodPlugins,
],
}
在上面的代码中,首先判断是否在生产阶段,如果是采用 babel-plugin-transform-remove-console 插件,将其添加到 prodPlugins 数组中,然后再 plugins 中进行配置
生成打包报告
打包时,为了直观地发现项目中存在的问题,可以在打包时生成报告
- 通过命令行参数形式生成报告
// 通过vue-cli的命令选项可以生成打包报告
// --report 选项可以生成 report.html以帮助分析包内容
vue-cli-service build --report
- 通过可视化 UI 面板直接查看报告(推荐) 在可视化的 UI 面板中,通过控制台和分析面板,可以方便的看到项目中所存在的问题。例如:以来的文件(js,css)比较大,页面打开速度非常慢
通过 vue.config.js 修改 webpack 配置
通过脚手架工具生成的项目,默认隐藏了所以 webpack 的配置项,目的是为了屏蔽项目的配置过程,让程序员把工作的重心,放到具体功能和业务逻辑的实现上
如果程序员有修改 webpack 默认配置的需求,可以在项目根目录中,按需创建 vue.config.js 文件,从而对项目的打包打不过乘坐自定义的配置,具体配置请参考cli.vuejs.org/zh/config/#…
// vue.config.js
// 这个文件中,应该导出一个包含了自定义配置选项的对象
module.exports = {
// 选项...
}
为开发模式与发布模式指定不同的打包入口
默认情况下,Vue 项目的开发模式与发布模式,共用同一个打包的入口文件(即 src/main.js)。为了将项目 的开发过程与发布过程分离,我们可以为两种模式,各自指定打包的入口文件,即:
- 开发模式的入口文件为 src/main-dev.js
- 发布模式的入口文件为 src/main-prod.js
configureWebpack 和 chainWebpack
在 vue.config.js 导出的配置对象中,新增 configureWebpack 和 chainWebpack 节点,来自定义 webpack 的打包配置,在这里,configureWebpack 和 chainWebpack 的作用相同,唯一的区别就是它们修改 webpack 配置的方式不同:
- chainWebpack 通过链式编程的形式,来修改默认的 webpack 配置
- configureWebpack
通过操作对象的形式,来修改默认的 webpack 配置
两者具体的使用差异,可以参考如下网址:(cli.vuejs.org/zh/guide/we…]
通过 chainWebpack 自定义打包入口
代码示例如下:
:::tip
注意: 要将项目./src 目录下入口文件的 main.js 文件复制两份,分别命名为 main-prod.js(发布模式下的入口文件)和 main-dev.js(开发模式下的入口文件)
:::
module.exports = {
chainWebpack: (config) => {
//发布模式
config.when(process.env.NODE_ENV === 'production', (config) => {
//entry找到默认的打包入口,调用clear则是删除默认的打包入口
//add添加新的打包入口
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')
})
},
}
通过 externals 加载外部 CDN 资源
在我们打包项目的时候,会发现一些依赖包占用的空间很大,而现在很多的依赖包都在外部 CDN 服务器上有相应的资源,那么我们就可以使用外部 CDN 资源,减轻项目服务器的压力
默认情况下,通过 import 导入的第三方依赖包最终会被打包合并到同一个文件中,从而导致打包成功后出现单文件体积过大的问题
为了解决上述问题,可以通过 webpack 的 externals 节点来配置外部的 CDN 资源,凡是生命在 externals 中的第三方依赖包,都不会被打包
- 在 vue.config.js 的发布模式的方法快中添加代码
config.set('externals', {
// 如果在打包期间,发现import的一个包名为vue,就不会把这个包合并到文件中
// 而是去window全局查找 Vue 对象,并直接使用
vue: 'Vue',
'vue-router': 'VueRouter',
axios: 'axios',
lodash: '_',
echarts: 'echarts',
nprogress: 'NProgress',
'vue-quill-editor': 'VueQuillEditor',
})
- 把 main-prod.js 文件中引入的样式表删除
删除前
// 导入富文本编辑器
import VueQuillEditor from 'vue-quill-editor'
// require styles 导入富文本编辑器对应的样式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
// 导入 NProgress 包对应的JS和CSS
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
删除后
// 导入富文本编辑器
import VueQuillEditor from 'vue-quill-editor'
// 导入 NProgress 包对应的JS和CSS
import NProgress from 'nprogress'
- 在 public/index.html 中添加如下 CDN 资源引用
<!-- nprogress 的样式表文件 -->
<link
rel="stylesheet"
href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css"
/>
<!-- 富文本编辑器 的样式表文件 -->
<link
rel="stylesheet"
href="https://cdn.staticfile.org/quill/1.3.4/quill.core.min.css"
/>
<link
rel="stylesheet"
href="https://cdn.staticfile.org/quill/1.3.4/quill.snow.min.css"
/>
<link
rel="stylesheet"
href="https://cdn.staticfile.org/quill/1.3.4/quill.bubble.min.css"
/>
<script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<script src="https://cdn.staticfile.org/lodash.js/4.17.11/lodash.min.js"></script>
<script src="https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js"></script>
<script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
<!-- 富文本编辑器的 js 文件 -->
<script src="https://cdn.staticfile.org/quill/1.3.4/quill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js"></script>
- 那如果要把 element-ui 也优化了,通过 CDN 资源引入呢? 其实也是一样的步骤,首先将导入的语句删除或注释掉,然后在 index.html 中引入 element-ui 的 JS 和 CSS 样式链接
<!-- 链接也可以在官方文档获取 -->
<!-- element-ui 的样式表文件 -->
<link
rel="stylesheet"
href="https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css"
/>
<!-- element-ui 的 js 文件 -->
<script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js"></script>
首页内容定制
不同的打包环境下,首页内容可能会有所不同,我们可以通过插件的方式进行定时,插件配置如下:
chainWebpack: (config) => {
config.when(process.env.NODE_ENV === 'production', (config) => {
config.plugin('html').tap((args) => {
args[0].isProd = true
return args
})
})
config.when(process.env.NODE_ENV === 'development', (config) => {
config.plugin('html').tap((args) => {
args[0].isProd = false
return args
})
})
}
在 public/index.html 首页中,可以根据 isProd 的值,来决定如何渲染页面结构:
<!-- 按需渲染页面的标题 -->
<title>
<%= htmlWebpackPlugin.options.isProd ? ' ' : 'dev - ' %>电商后台管理系统</title
>;
<!-- 按需加载外部的 CDN 资源-->
<% if(htmlWebpackPlugin.options.isProd) { %>
<!-- 通过 externals 加载的外部 CDN 资源-->
<% } %>
打开 vue.config.js 添加代码:
module.exports = {
chainWebpack: (config) => {
// 发布模式--发布阶段的打包入口
config.when(process.env.NODE_ENV === 'production', (config) => {
config
.entry('app')
.clear()
.add('./src/main-prod.js')
// externals 加载外部 CDN 资源
config.set('externals', {
vue: 'Vue',
'vue-router': 'VueRouter',
axios: 'axios',
lodash: '_',
echarts: 'echarts',
nprogress: 'NProgress',
'vue-quill-editor': 'VueQuillEditor',
})
// 首页定制
config.plugin('html').tap((args) => {
args[0].isProd = true
return args
})
})
// 开发模式--开发阶段的打包入口
config.when(process.env.NODE_ENV === 'development', (config) => {
config
.entry('app')
.clear()
.add('./src/main-dev.js')
// 首页定制
config.plugin('html').tap((args) => {
args[0].isProd = false
return args
})
})
},
}
打开 index.html 文件:
<title>
<%= htmlWebpackPlugin.options.isProd ? '' : 'dev - ' %>电商后台管理系统
</title>
<!-- 按需加载外部的 CDN 资源-->
<% if(htmlWebpackPlugin.options.isProd) { %>
<!-- nprogress 的样式表文件 -->
<link
rel="stylesheet"
href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css"
/>
<!-- 富文本编辑器的样式表文件 -->
<link
rel="stylesheet"
href="https://cdn.staticfile.org/quill/1.3.6/quill.core.min.css"
/>
<link
rel="stylesheet"
href="https://cdn.staticfile.org/quill/1.3.6/quill.snow.min.css"
/>
<link
rel="stylesheet"
href="https://cdn.staticfile.org/quill/1.3.6/quill.bubble.min.css"
/>
<!-- element-ui 的样式表文件 -->
<link
rel="stylesheet"
href="https://cdn.staticfile.org/element-ui/2.13.0/theme-chalk/index.css"
/>
<!-- element-ui 的js文件 -->
<script src="https://cdn.staticfile.org/element-ui/2.13.0/index.js"></script>
<script src="https://cdn.staticfile.org/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/3.1.3/vue-router.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.19.0/axios.min.js"></script>
<script src="https://cdn.staticfile.org/lodash.js/4.17.15/lodash.min.js"></script>
<script src="https://cdn.staticfile.org/echarts/4.7.0/echarts.min.js"></script>
<script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
<!-- 富文本编辑器的js文件-->
<script src="https://cdn.staticfile.org/quill/1.3.6/quill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.6/dist/vue-quill-editor.js"></script>
<% } %>
打开可视化 UI 面板,在 serve 中先停止,然后重新运行,此时项目可以正常跑起来了,前面路由重定义的问题就解决了。
然后在 build 中,点击运行。编辑成功后,打开 dist 文件夹的 index.html 文件,可以发现 title 和 引用的加载外部的 CDN 资源。
路由懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
- 安装 @babel/plugin-syntax-dynamic-import 包。
- 在 babel.config.js 配置文件中声明该插件。
//项目发布阶段需要用到的babel插件
const productPlugins = []
//判断是开发还是发布阶段
if (process.env.NODE_ENV === 'production') {
//发布阶段
productPlugins.push('transform-remove-console')
}
module.exports = {
presets: ['@vue/app'],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk',
},
],
...productPlugins,
//配置路由懒加载插件
'@babel/plugin-syntax-dynamic-import',
],
}
- 将路由改为按需加载的形式,打开路由的 js 文件,/src/router/index.js 示例代码如下:
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-boo" */ './Baz.vue')
示例:
// import Login from './components/Login.vue'
const Login = () =>
import(/* webpackChunkName: "login_home_welcome" */ './components/Login.vue')
// import Home from './components/Home.vue'
const Home = () =>
import(/* webpackChunkName: "login_home_welcome" */ './components/Home.vue')
// import Welcome from './components/Welcome.vue'
const Welcome = () =>
import(
/* webpackChunkName: "login_home_welcome" */ './components/Welcome.vue'
)
// import Users from './components/user/Users.vue'
const Users = () =>
import(
/* webpackChunkName: "Users_Rights_Roles" */ './components/user/Users.vue'
)
// import Rights from './components/power/Rights.vue'
const Rights = () =>
import(
/* webpackChunkName: "Users_Rights_Roles" */ './components/power/Rights.vue'
)
// import Roles from './components/power/Roles.vue'
const Roles = () =>
import(
/* webpackChunkName: "Users_Rights_Roles" */ './components/power/Roles.vue'
)
(参考文档)[router.vuejs.org/zh/guide/ad…]
项目部署上线
关于项目部署上线,主要完成以下的配置
- 通过 node 创建 web 服务器 创建 node 项目,并安装 express,通过 express 快速创建 web 服务器,将 vue 打包生成的 dist 文件夹 托管为静态资源即可,关键代码如下:
const express = require('express')
//创建 web 服务器
const app = express()
//托管静态资源
app.use(express.static('./dist'))
//启动web服务器
app.listen(80, () => {
console.log('web server running at http://127.0.0.1')
})
- 开启 gzip 配置
使用 gzip 可以减小文件体积,使传输速度更快
可以通过服务器端使用 Express 做 gzip 压缩。其配置如下:
// 安装响应包
npm install compression -S
// 导入包
const compression = require('compression')
// 启用中间件
app.use(compression)
具体实现如下所示,修改 app.js 文件中的代码
const express = require('express')
// 创建web服务器
const app = express()
const compression = require('compression')
// 一定要把这一行代码,写到静态资源托管之前
app.use(compression)
// 托管静态资源
app.use(express.static('./dist'))
// 启动web服务器
app.listen(8080, () => {
console.log('web server running at http://127.0.0.1')
})
- 配置 https 服务
- 使用 pm2 管理应用