• 第八节:项目优化上线之打包、报告分析、删除console、webpack配置、CDN、首页定制、路由懒加载、Express部署和管理


    一. 项目优化

    1. 生成发布包

     根目录下运行指令【npm run build】,会生出一个dist文件夹,该文件夹就是项目生成的发布包,可以直接放到IIS中部署即可。

     

    2. 生成/分析打包报告

     A. 命令行形式生成打包报告 vue-cli-service build --report 】

     B. 在vue控制台(图形化界面  【vue ui】)生成打包报告 点击“任务”=>“build”=>“运行” 运行完毕之后点击右侧“分析”,“控制台”面板查看报告。 (推荐)

    3. 删除console.log

     我们想在想在项目的build阶段移除所有的Console信息。 

     步骤:运行指令【npm i babel-plugin-transform-remove-console -D】,然后在babel.config.js文件中进行添加下面代码:

    // 这是项目发布阶段需要用到的 babel-plugin-transform-remove-console 插件
    const prodPlugins = []
    if (process.env.NODE_ENV === 'production') {
      // 发布时候去掉console
      prodPlugins.push('transform-remove-console')
    }
    
    module.exports = {
      presets: [
        '@vue/cli-plugin-babel/preset'
      ],
      plugins: [
        [
          'component',
          {
            libraryName: 'element-ui',
            styleLibraryName: 'theme-chalk'
          }
        ],
        // 发布产品时候的插件数组
        ...prodPlugins
      ]
    }

    4. 修改webpack的默认配置

     默认情况下,vue-cli 4.0生成的项目,隐藏了webpack配置项,如果我们需要配置webpack 需要通过vue.config.js来配置。

     步骤:我们将main.js文件改成两个: main-dev.js (开发专用) 、main-prod.js(生产专用) ,然后在vue.config.js中进行配置,让它打包的时候用的是main-prod.js,开发调试的时候,用的是main-dev.js,下面是vue.config.js的配置:

    module.exports = {
      devServer: {
        port: 8086,
        open: true
      },
      // chainWebpack可以通过链式编程的形式,修改webpack配置   或者   configureWebpack可以通过操作对象的形式,修改webpack配置
      chainWebpack: config => {
        //1. 发布模式
        config.when(process.env.NODE_ENV === 'production', config => {
          //1.1 entry找到默认的打包入口,调用clear则是删除默认的打包入口
          //add添加新的打包入口
          config.entry('app').clear().add('./src/main-prod.js')
        });
    
        //2. 开发模式
        config.when(process.env.NODE_ENV === 'development', config => {
          config.entry('app').clear().add('./src/main-dev.js')
        })
      },
    }

    5. 加载外部CDN

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

    步骤:

    (1).在vue.config.js中进行代码排除(排除 Vue、VueRouter、axios、echarts、NProgress、VueQuillEditor等第三方包)

    //1. 发布模式
        config.when(process.env.NODE_ENV === 'production', config => {
          //1.1 entry找到默认的打包入口,调用clear则是删除默认的打包入口
          //add添加新的打包入口
          config.entry('app').clear().add('./src/main-prod.js')
    
          //1.2 使用externals设置排除项。默认情况下,依赖项的所有第三方包都会被打包到js/chunk-vendors.******.js文件中,导致该js文件过大;
          // 那么我们可以通过externals排除这些包,使它们不被打包到js/chunk-vendors.******.js文件中
          config.set('externals', {
            vue: 'Vue',
            'vue-router': 'VueRouter',
            axios: 'axios',
            lodash: '_',
            echarts: 'echarts',
            nprogress: 'NProgress',
            'vue-quill-editor': 'VueQuillEditor'
          })
    
        });

    (2). 在main-prod.js文件中注释掉相应的导入

    // 生产环境
    import Vue from 'vue'
    import App from './App.vue'
    // 导入路由(等价 import router from './router/index.js')
    import router from './router'
    // 导入ElementUI
    // import './plugins/element.js'
    // 导入字体图标
    import './assets/fonts/iconfont.css'
    // 导入全局样式表
    import './assets/css/global.css'
    
    // 导入 NProgress 包对应的JS和CSS
    import NProgress from 'nprogress'
    // import 'nprogress/nprogress.css'
    
    // 导入富文本编辑器
    import VueQuillEditor from 'vue-quill-editor'
    //导入富文本编辑器对应的样式
    // import 'quill/dist/quill.core.css'
    // import 'quill/dist/quill.snow.css'
    // import 'quill/dist/quill.bubble.css'
    // 将富文本编辑器,注册为全局可用的组件
    Vue.use(VueQuillEditor)
    
    // 导入表格自适应方法
    import adaptive from './utils/table-adapter'
    Vue.use(adaptive)
    
    // 导入axios并进行配置
    import axios from 'axios'
    axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
    axios.interceptors.request.use(config => {
      NProgress.start();
      // 添加表头信息
      config.headers.Authorization = window.sessionStorage.getItem('token');
      return config;
    })
    // 在 response 拦截器中,隐藏进度条 NProgress.done()
    axios.interceptors.response.use(config => {
      NProgress.done();
      return config;
    })
    Vue.prototype.$http = axios
    
    // 注册全局日期过滤器
    Vue.filter('dateFormat', function(originVal) {
      const dt = new Date(originVal);
      const y = dt.getFullYear();
      const m = (dt.getMonth() + 1 + '').padStart(2, '0');
      const d = (dt.getDate() + '').padStart(2, '0');
      const hh = (dt.getHours() + '').padStart(2, '0');
      const mm = (dt.getMinutes() + '').padStart(2, '0');
      const ss = (dt.getSeconds() + '').padStart(2, '0');
      return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
    })
    
    Vue.config.productionTip = false
    new Vue({
      router,
      render: h => h(App)
    }).$mount('#app')
    View Code

    (3). 在public/index.html中对上述注释掉的包使用cdn的方式进行导入

     这里需要注意的是,只有生产环境才需要cdn导入,需要配置一个参数来区分,详见下面的【6. 定制首页内容】

    <!DOCTYPE html>
    <html lang="">
      <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 ? '' : '开发 - ' %>后台管理系统</title>
            
            <!-- 下面代表只有生产环境才加载cdn -->
            <% if(htmlWebpackPlugin.options.isProd){ %>
            <!-- nprogress 的样式表文件 -->
            <link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
            <!-- 富文本编辑器 的样式表文件 no -->
            <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" />
            <!-- element-ui 的样式表文件 -->
            <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.15.1/theme-chalk/index.css" />
            <!-- 下面是相关的js文件 -->
            <script src="https://cdn.staticfile.org/vue/2.6.11/vue.min.js"></script>
            <script src="https://cdn.staticfile.org/vue-router/3.2.0/vue-router.min.js"></script>
            <script src="https://cdn.staticfile.org/axios/0.21.1/axios.min.js"></script>
            <script src="https://cdn.staticfile.org/lodash.js/4.17.21/lodash.min.js"></script>
            <script src="https://cdn.staticfile.org/echarts/5.0.2/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.6/dist/vue-quill-editor.js"></script>
            <!-- element-ui 的 js 文件 -->
            <script src="https://cdn.staticfile.org/element-ui/2.15.1/index.js"></script>
            <% } %>
            
            
            
      </head>
      <body>
        <noscript>
          <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
      </body>
    </html>
    View Code

    6. 定制首页内容

     这里我们需要配置一个参数,用来区分是生产 还是 开发,从而决定首页的显示 和 是否加载cdn。

    步骤:

    (1). 在vue.config.js中进行首页参数的地址,isProd生产环境为ture, 开发环境为falses。

    module.exports = {
      devServer: {
        port: 8086,
        open: true
      },
      // chainWebpack可以通过链式编程的形式,修改webpack配置   或者   configureWebpack可以通过操作对象的形式,修改webpack配置
      chainWebpack: config => {
        //1. 发布模式
        config.when(process.env.NODE_ENV === 'production', config => {
          //1.1 entry找到默认的打包入口,调用clear则是删除默认的打包入口
          //add添加新的打包入口
          config.entry('app').clear().add('./src/main-prod.js')
    
          //1.2 使用externals设置排除项。默认情况下,依赖项的所有第三方包都会被打包到js/chunk-vendors.******.js文件中,导致该js文件过大;
          // 那么我们可以通过externals排除这些包,使它们不被打包到js/chunk-vendors.******.js文件中
          config.set('externals', {
            vue: 'Vue',
            'vue-router': 'VueRouter',
            axios: 'axios',
            lodash: '_',
            echarts: 'echarts',
            nprogress: 'NProgress',
            'vue-quill-editor': 'VueQuillEditor'
          })
    
          //1.3 定制首页内容
          config.plugin('html').tap(args => {
            //添加参数isProd,true代表生产环境
            args[0].isProd = true
            return args
          })
    
    
        });
    
    
        //2. 开发模式
        config.when(process.env.NODE_ENV === 'development', config => {
          config.entry('app').clear().add('./src/main-dev.js')
    
          // 定制首页内容
          config.plugin('html').tap(args => {
            //添加参数isProd, false代表开发环境
            args[0].isProd = false
            return args
          })
    
        })
    
      },
    
    
    }
    View Code

    (2). 在public/index.html中,根据isProd进行判断即可。

    <!DOCTYPE html>
    <html lang="">
      <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 ? '' : '开发 - ' %>后台管理系统</title>
            
            <!-- 下面代表只有生产环境才加载cdn -->
            <% if(htmlWebpackPlugin.options.isProd){ %>
            <!-- nprogress 的样式表文件 -->
            <link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
            <!-- 富文本编辑器 的样式表文件 no -->
            <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" />
            <!-- element-ui 的样式表文件 -->
            <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.15.1/theme-chalk/index.css" />
            <!-- 下面是相关的js文件 -->
            <script src="https://cdn.staticfile.org/vue/2.6.11/vue.min.js"></script>
            <script src="https://cdn.staticfile.org/vue-router/3.2.0/vue-router.min.js"></script>
            <script src="https://cdn.staticfile.org/axios/0.21.1/axios.min.js"></script>
            <script src="https://cdn.staticfile.org/lodash.js/4.17.21/lodash.min.js"></script>
            <script src="https://cdn.staticfile.org/echarts/5.0.2/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.6/dist/vue-quill-editor.js"></script>
            <!-- element-ui 的 js 文件 -->
            <script src="https://cdn.staticfile.org/element-ui/2.15.1/index.js"></script>
            <% } %>
            
            
            
      </head>
      <body>
        <noscript>
          <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
      </body>
    </html>
    View Code

    7.路由懒加载

    (1). 通过指令【npm i @babel/plugin-syntax-dynamic-import -D】进行开发依赖的安装。

    (2). 在babel.config.js中声明该插件

    module.exports = {
      presets: [
        '@vue/cli-plugin-babel/preset'
      ],
      plugins: [
        [
          'component',
          {
            libraryName: 'element-ui',
            styleLibraryName: 'theme-chalk'
          }
        ],
        // 发布产品时候的插件数组
        ...prodPlugins,
        //配置路由懒加载插件
        "@babel/plugin-syntax-dynamic-import"
      ]
    }
    View Code

    (3). 在router/index.js中进行路由懒加载的改造

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    // import Login from '../components/Login.vue'
    // // @代表根路径
    // import Home from '@/components/Home.vue'
    // import Welcome from '@/components/Welcome.vue'
    // import Users from '@/components/user/Users.vue'
    // import Rights from '@/components/power/Rights.vue'
    // import Roles from '@/components/power/Roles.vue'
    // import Params from '@/components/goods/Params.vue'
    // import GoodsList from '@/components/goods/List.vue'
    // import Add from '@/components/goods/Add.vue'
    // import Order from '@/components/order/Order.vue'
    // import Report from '@/components/report/Report.vue'
    
    // 下面改成路由懒加载
    const Login = () => import('../components/Login.vue')
    const Home = () => import('@/components/Home.vue')
    const Welcome = () => import('@/components/Welcome.vue')
    const Users = () => import('@/components/user/Users.vue')
    const Rights = () => import('@/components/power/Rights.vue')
    const Roles = () => import('@/components/power/Roles.vue')
    const Params = () => import('@/components/goods/Params.vue')
    const GoodsList = () => import('@/components/goods/List.vue')
    const Add = () => import('@/components/goods/Add.vue')
    const Order = () => import('@/components/order/Order.vue')
    const Report = () => import('@/components/report/Report.vue')
    Vue.use(VueRouter)
    
    const router = new VueRouter({
      routes: [{
        path: '/',
        redirect: '/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: '/params',
          component: Params
        },
        {
          path: '/goods',
          component: GoodsList
        },
        {
          path: '/goods/add',
          component: Add
        },
        {
          path: '/orders',
          component: Order
        },
        {
          path: '/reports',
          component: Report
        }
        ]
      }
      ]
    })
    
    // 挂载路由导航守卫
    router.beforeEach((to, from, next) => {
      // to 将要访问的路径
      // from 代表从哪个路径跳转而来
      // next 是一个函数,表示放行
      // next()  放行    next('/login')  强制跳转
      if (to.path === '/login') return next()
      // 获取token
      const tokenStr = window.sessionStorage.getItem('token')
      if (!tokenStr) return next('/login')
      next()
    })
    
    // 默认导出
    export default router
    View Code

    8. 重新制作发布包,分析报告

     警告没了,生产的js文件缩小的很多!!!

    二. 项目部署

    1. 直接IIS部署

      直接放到IIS下部署即可。

    2. 通过express部署

    (1). 步骤

     A. 创建vue_publish文件夹,输入命令【 npm init -y 】初始化包

     B. 输入命令【 npm i express -S】,进行express的安装 

     C. 复制dist文件夹,粘贴到vue_publish中

     D. 在该文件夹下创建app.js文件,编写代码如下:

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

     E. 运行【npm install】安装所有运行包

     F. 运行【node app.js】启动项目,然后 访问 http://127.0.0.1:8998 即可。

    (2). 开启Gzip压缩

     A. 运行指令【npm i compression -D】

     B. app.js中添加两行代码

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

    (3). 使用pm2管理应用

    A. 全局安装pm2 【npm i pm2 -g】

    B. 在发布包根目录下运行指令【pm2 start app.js --name 自定义名称】,启动项目。

    PS:其它指令

     查看项目列表命令:pm2 ls

     重启项目:pm2 restart 自定义名称

     停止项目:pm2 stop 自定义名称

     删除项目:pm2 delete 自定义名称

     

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    js 自定义事件
    django项目mysite
    python web 框架
    Python web-Http
    numpy学习
    django 中单独执行py文件修改用户名
    python解决排列组合
    解决Database returned an invalid datetime value. Are time zone definitions for your database installed?
    Anaconda下载地址
    Django中使用geetest实现滑动验证
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/14549481.html
Copyright © 2020-2023  润新知