今日目标

1.完成项目优化
2.完成项目上线

1.项目优化

实现步骤:
A.生成打包报告,根据报告优化项目
B.第三方库启用CDN
C.Element-UI组件按需加载
D.路由懒加载
E.首页内容定制

2.添加进度条

给项目添加进度条效果,先打开项目控制台,打开依赖,安装nprogress
打开main.js,编写如下代码

  1. //导入进度条插件
  2. import NProgress from 'nprogress'
  3. //导入进度条样式
  4. import 'nprogress/nprogress.css'
  5. .....
  6. //请求在到达服务器之前,先会调用use中的这个回调函数来添加请求头信息
  7. axios.interceptors.request.use(config => {
  8. //当进入request拦截器,表示发送了请求,我们就开启进度条
  9. NProgress.start()
  10. //为请求头对象,添加token验证的Authorization字段
  11. config.headers.Authorization = window.sessionStorage.getItem("token")
  12. //必须返回config
  13. return config
  14. })
  15. //在response拦截器中,隐藏进度条
  16. axios.interceptors.response.use(config =>{
  17. //当进入response拦截器,表示请求已经结束,我们就结束进度条
  18. NProgress.done()
  19. return config
  20. })

3.根据报错修改代码

根据ESLint的警告提示更改对应的代码
在.prettierrc文件中更改设置”printWidth”:200, 将每行代码的文字数量更改为200

  1. {
  2. "semi":false,
  3. "singleQuote":true,
  4. "printWidth":200
  5. }

4.执行build

安装一个插件(babel-plugin-transform-remove-console)在项目build阶段移除所有的console信息
打开项目控制台,点击依赖->开发依赖,输入babel-plugin-transform-remove-console,安装
打开babel.config.js,编辑代码如下:

  1. //项目发布阶段需要用到的babel插件
  2. const productPlugins = []
  3. //判断是开发还是发布阶段
  4. if(process.env.NODE_ENV === 'production'){
  5. //发布阶段
  6. productPlugins.push("transform-remove-console")
  7. }
  8. module.exports = {
  9. "presets": [
  10. "@vue/app"
  11. ],
  12. "plugins": [
  13. [
  14. "component",
  15. {
  16. "libraryName": "element-ui",
  17. "styleLibraryName": "theme-chalk"
  18. }
  19. ],
  20. ...productPlugins
  21. ]
  22. }

5.生成打包报告

A.命令行形式生成打包报告
vue-cli-service build —report
B.在vue控制台生成打包报告
点击“任务”=>“build”=>“运行”
运行完毕之后点击右侧“分析”,“控制台”面板查看报告

6.修改webpack的默认配置

默认情况下,vue-cli 3.0生成的项目,隐藏了webpack配置项,如果我们需要配置webpack
需要通过vue.config.js来配置。
在项目根目录中创建vue.config.js文件,

  1. module.exports = {
  2. chainWebpack:config=>{
  3. //发布模式
  4. config.when(process.env.NODE_ENV === 'production',config=>{
  5. //entry找到默认的打包入口,调用clear则是删除默认的打包入口
  6. //add添加新的打包入口
  7. config.entry('app').clear().add('./src/main-prod.js')
  8. })
  9. //开发模式
  10. config.when(process.env.NODE_ENV === 'development',config=>{
  11. config.entry('app').clear().add('./src/main-dev.js')
  12. })
  13. }
  14. }

补充:
chainWebpack可以通过链式编程的形式,修改webpack配置
configureWebpack可以通过操作对象的形式,修改webpack配置

7.加载外部CDN

默认情况下,依赖项的所有第三方包都会被打包到js/chunk-vendors..js文件中,导致该js文件过大
那么我们可以通过externals排除这些包,使它们不被打包到js/chunk-vendors.
.js文件中

  1. module.exports = {
  2. chainWebpack:config=>{
  3. //发布模式
  4. config.when(process.env.NODE_ENV === 'production',config=>{
  5. //entry找到默认的打包入口,调用clear则是删除默认的打包入口
  6. //add添加新的打包入口
  7. config.entry('app').clear().add('./src/main-prod.js')
  8. //使用externals设置排除项
  9. config.set('externals',{
  10. vue:'Vue',
  11. 'vue-router':'VueRouter',
  12. axios:'axios',
  13. lodash:'_',
  14. echarts:'echarts',
  15. nprogress:'NProgress',
  16. 'vue-quill-editor':'VueQuillEditor'
  17. })
  18. })
  19. //开发模式
  20. config.when(process.env.NODE_ENV === 'development',config=>{
  21. config.entry('app').clear().add('./src/main-dev.js')
  22. })
  23. }
  24. }

设置好排除之后,为了使我们可以使用vue,axios等内容,我们需要加载外部CDN的形式解决引入依赖项。
打开开发入口文件main-prod.js,删除掉默认的引入代码

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import router from './router'
  4. // import './plugins/element.js'
  5. //导入字体图标
  6. import './assets/fonts/iconfont.css'
  7. //导入全局样式
  8. import './assets/css/global.css'
  9. //导入第三方组件vue-table-with-tree-grid
  10. import TreeTable from 'vue-table-with-tree-grid'
  11. //导入进度条插件
  12. import NProgress from 'nprogress'
  13. //导入进度条样式
  14. // import 'nprogress/nprogress.css'
  15. // //导入axios
  16. import axios from 'axios'
  17. // //导入vue-quill-editor(富文本编辑器)
  18. import VueQuillEditor from 'vue-quill-editor'
  19. // //导入vue-quill-editor的样式
  20. // import 'quill/dist/quill.core.css'
  21. // import 'quill/dist/quill.snow.css'
  22. // import 'quill/dist/quill.bubble.css'
  23. axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
  24. //请求在到达服务器之前,先会调用use中的这个回调函数来添加请求头信息
  25. axios.interceptors.request.use(config => {
  26. //当进入request拦截器,表示发送了请求,我们就开启进度条
  27. NProgress.start()
  28. //为请求头对象,添加token验证的Authorization字段
  29. config.headers.Authorization = window.sessionStorage.getItem("token")
  30. //必须返回config
  31. return config
  32. })
  33. //在response拦截器中,隐藏进度条
  34. axios.interceptors.response.use(config =>{
  35. //当进入response拦截器,表示请求已经结束,我们就结束进度条
  36. NProgress.done()
  37. return config
  38. })
  39. Vue.prototype.$http = axios
  40. Vue.config.productionTip = false
  41. //全局注册组件
  42. Vue.component('tree-table', TreeTable)
  43. //全局注册富文本组件
  44. Vue.use(VueQuillEditor)
  45. //创建过滤器将秒数过滤为年月日,时分秒
  46. Vue.filter('dateFormat',function(originVal){
  47. const dt = new Date(originVal)
  48. const y = dt.getFullYear()
  49. const m = (dt.getMonth()+1+'').padStart(2,'0')
  50. const d = (dt.getDate()+'').padStart(2,'0')
  51. const hh = (dt.getHours()+'').padStart(2,'0')
  52. const mm = (dt.getMinutes()+'').padStart(2,'0')
  53. const ss = (dt.getSeconds()+'').padStart(2,'0')
  54. return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
  55. })
  56. new Vue({
  57. router,
  58. render: h => h(App)
  59. }).$mount('#app')

然后打开public/index.html添加外部cdn引入代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width,initial-scale=1.0">
  7. <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  8. <title>电商后台管理系统</title>
  9. <!-- nprogress 的样式表文件 -->
  10. <link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
  11. <!-- 富文本编辑器 的样式表文件 -->
  12. <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.core.min.css" />
  13. <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.snow.min.css" />
  14. <link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.bubble.min.css" />
  15. <!-- element-ui 的样式表文件 -->
  16. <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css" />
  17. <script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
  18. <script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js"></script>
  19. <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
  20. <script src="https://cdn.staticfile.org/lodash.js/4.17.11/lodash.min.js"></script>
  21. <script src="https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js"></script>
  22. <script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
  23. <!-- 富文本编辑器的 js 文件 -->
  24. <script src="https://cdn.staticfile.org/quill/1.3.4/quill.min.js"></script>
  25. <script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js"></script>
  26. <!-- element-ui 的 js 文件 -->
  27. <script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js"></script>
  28. </head>
  29. <body>
  30. <noscript>
  31. <strong>We're sorry but vue_shop doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
  32. </noscript>
  33. <div id="app"></div>
  34. <!-- built files will be auto injected -->
  35. </body>
  36. </html>

8.定制首页内容

开发环境的首页和发布环境的首页展示内容的形式有所不同
如开发环境中使用的是import加载第三方包,而发布环境则是使用CDN,那么首页也需根据环境不同来进行不同的实现
我们可以通过插件的方式来定制首页内容,打开vue.config.js,编写代码如下:

  1. module.exports = {
  2. chainWebpack:config=>{
  3. config.when(process.env.NODE_ENV === 'production',config=>{
  4. ......
  5. //使用插件
  6. config.plugin('html').tap(args=>{
  7. //添加参数isProd
  8. args[0].isProd = true
  9. return args
  10. })
  11. })
  12. config.when(process.env.NODE_ENV === 'development',config=>{
  13. config.entry('app').clear().add('./src/main-dev.js')
  14. //使用插件
  15. config.plugin('html').tap(args=>{
  16. //添加参数isProd
  17. args[0].isProd = false
  18. return args
  19. })
  20. })
  21. }
  22. }

然后在public/index.html中使用插件判断是否为发布环境并定制首页内容

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width,initial-scale=1.0">
  7. <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  8. <title><%= htmlWebpackPlugin.options.isProd ? '' : 'dev - ' %>电商后台管理系统</title>
  9. <% if(htmlWebpackPlugin.options.isProd){ %>
  10. <!-- nprogress 的样式表文件 -->
  11. <link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
  12. ........
  13. <!-- element-ui 的 js 文件 -->
  14. <script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js"></script>
  15. <% } %>
  16. </head>
  17. .......

9.路由懒加载

当路由被访问时才加载对应的路由文件,就是路由懒加载。
路由懒加载实现步骤:
1.安装 @babel/plugin-syntax-dynamic-import
打开vue控制台,点击依赖->安装依赖->开发依赖->搜索@babel/plugin-syntax-dynamic-import
点击安装。
2.在babel.config.js中声明该插件,打开babel.config.js

  1. //项目发布阶段需要用到的babel插件
  2. const productPlugins = []
  3. //判断是开发还是发布阶段
  4. if(process.env.NODE_ENV === 'production'){
  5. //发布阶段
  6. productPlugins.push("transform-remove-console")
  7. }
  8. module.exports = {
  9. "presets": [
  10. "@vue/app"
  11. ],
  12. "plugins": [
  13. [
  14. "component",
  15. {
  16. "libraryName": "element-ui",
  17. "styleLibraryName": "theme-chalk"
  18. }
  19. ],
  20. ...productPlugins,
  21. //配置路由懒加载插件
  22. "@babel/plugin-syntax-dynamic-import"
  23. ]
  24. }

3.将路由更改为按需加载的形式,打开router.js,更改引入组件代码如下:

  1. import Vue from 'vue'
  2. import Router from 'vue-router'
  3. const Login = () => import(/* webpackChunkName:"login_home_welcome" */ './components/Login.vue')
  4. // import Login from './components/Login.vue'
  5. const Home = () => import(/* webpackChunkName:"login_home_welcome" */ './components/Home.vue')
  6. // import Home from './components/Home.vue'
  7. const Welcome = () => import(/* webpackChunkName:"login_home_welcome" */ './components/Welcome.vue')
  8. // import Welcome from './components/Welcome.vue'
  9. const Users = () => import(/* webpackChunkName:"user" */ './components/user/Users.vue')
  10. // import Users from './components/user/Users.vue'
  11. const Rights = () => import(/* webpackChunkName:"power" */ './components/power/Rights.vue')
  12. // import Rights from './components/power/Rights.vue'
  13. const Roles = () => import(/* webpackChunkName:"power" */ './components/power/Roles.vue')
  14. // import Roles from './components/power/Roles.vue'
  15. const Cate = () => import(/* webpackChunkName:"goods" */ './components/goods/Cate.vue')
  16. // import Cate from './components/goods/Cate.vue'
  17. const Params = () => import(/* webpackChunkName:"goods" */ './components/goods/Params.vue')
  18. // import Params from './components/goods/Params.vue'
  19. const GoodList = () => import(/* webpackChunkName:"goods" */ './components/goods/List.vue')
  20. // import GoodList from './components/goods/List.vue'
  21. const GoodAdd = () => import(/* webpackChunkName:"goods" */ './components/goods/Add.vue')
  22. // import GoodAdd from './components/goods/Add.vue'
  23. const Order = () => import(/* webpackChunkName:"order" */ './components/order/Order.vue')
  24. // import Order from './components/order/Order.vue'
  25. const Report = () => import(/* webpackChunkName:"report" */ './components/report/Report.vue')
  26. // import Report from './components/report/Report.vue'

10.项目上线

A.通过node创建服务器

在vue_shop同级创建一个文件夹vue_shop_server存放node服务器
使用终端打开vue_shop_server文件夹,输入命令 npm init -y
初始化包之后,输入命令 npm i express -S
打开vue_shop目录,复制dist文件夹,粘贴到vue_shop_server中
在vue_shop_server文件夹中创建app.js文件,编写代码如下:

  1. const express = require('express')
  2. const app = express()
  3. app.use(express.static('./dist'))
  4. app.listen(8998,()=>{
  5. console.log("server running at http://127.0.0.1:8998")
  6. })

然后再次在终端中输入 node app.js

B.开启gzip压缩

打开vue_shop_server文件夹的终端,输入命令:npm i compression -D
打开app.js,编写代码:

  1. const express = require('express')
  2. const compression = require('compression')
  3. const app = express()
  4. app.use(compression())
  5. app.use(express.static('./dist'))
  6. app.listen(8998,()=>{
  7. console.log("server running at http://127.0.0.1:8998")
  8. })

C.配置https服务

配置https服务一般是后台进行处理,前端开发人员了解即可。
首先,需要申请SSL证书,进入https://freessl.cn官网
在后台导入证书,打开今天资料/素材,复制素材中的两个文件到vue_shop_server中
打开app.js文件,编写代码导入证书,并开启https服务

  1. const express = require('express')
  2. const compression = require('compression')
  3. const https = require('https')
  4. const fs = require('fs')
  5. const app = express()
  6. //创建配置对象设置公钥和私钥
  7. const options = {
  8. cert:fs.readFileSync('./full_chain.pem'),
  9. key:fs.readFileSync('./private.key')
  10. }
  11. app.use(compression())
  12. app.use(express.static('./dist'))
  13. // app.listen(8998,()=>{
  14. // console.log("server running at http://127.0.0.1:8998")
  15. // })
  16. //启动https服务
  17. https.createServer(options,app).listen(443)

注意:因为我们使用的证书有问题,所以无法正常使用https服务

D.使用pm2管理应用

打开vue_shop_server文件夹的终端,输入命令:npm i pm2 -g
使用pm2启动项目,在终端中输入命令:pm2 start app.js —name 自定义名称
查看项目列表命令:pm2 ls
重启项目:pm2 restart 自定义名称
停止项目:pm2 stop 自定义名称
删除项目:pm2 delete 自定义名称