Vue+express项目优化上线(1)

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 语法导入的第三方依赖包,最终会被打包合并到一个文件中,导致打包成功后,单文件体积过大问题

  • 通过webpackexternals节点,配置并加载外部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大文件被分割成数个小文件

2.项目上线

上一篇:Django--JWT认证


下一篇:django基础之初始化 views视图 (6)