【vue-cli】vue_shop电商后台管理项目优化,项目上线

完成项目的开发阶段,进入到发布阶段。


1. 添加进度条,修改代码,执行build

1. 添加进度条
给项目添加进度条效果,在项目控制台中,打开依赖,安装nprogress,打开main.js文件中,在axios请求拦截器和响应拦截器中添加如下代码(包括了携带token代码)

// 导入NProgress包对应的css 和js
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

// axios请求拦截器 请求头中携带token 展示进度条 NProgress.start()
axios.interceptors.request.use(config => {
    NProgress.start()
    config.headers.Authorization = window.sessionStorage.getItem('token') //Authorization为接口文件要求
    return config
});
// axios响应拦截器
axios.interceptors.response.use(config => {
    NProgress.done()
    return config
});

2. 根据报错修改代码
根据报告中的警告信息查询到具体问题代码
常见问题:

  1. 作用域定义scope未使用或其他变量未使用
  2. eslint与代码格式化冲突,在.prettierrc格式化配置文件内设置一行最多允许字符
{
    "semi": false, // 格式化不加分号
    "singleQuote": true// 格式化以单引号为主
    "printWidth": 200 // 格式化每行最多允许字符长度
}
  1. 变量最好为驼峰命名
  2. 文件过大,需要优化,可查阅下面的步骤

3. 执行build 移除所有console信息
安装插件,在项目控制台中,安装开发依赖babel-plugin-transform-remove-console,在babel.config.js编写如下代码(包含了懒加载插件代码)

// 这是项目发布阶段需要用到的 babel 插件,防止开发阶段的console也被移除
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'
            }
        ],
        // 发布产品时候的插件数组 移除console 懒加载
        ...prodPlugins,
        // 配置路由懒加载
        '@babel/plugin-syntax-dynamic-import'
    ]
}

2. 项目优化


【vue-cli】vue_shop电商后台管理项目优化,项目上线_第1张图片1. 生成打包报告,使用UI面板查看报告
在UI面板的打包报告中,可以看到打包的详细情况
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第2张图片【vue-cli】vue_shop电商后台管理项目优化,项目上线_第3张图片
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第4张图片


2. 通过vue.config.js修改webpack的默认配置

新建vue.config.js文件来修改webpack的默认配置,主要是当处于开发模式和发布模式不同情况下做不一样的事情,不用模式配置不同的打包入口文件(即以下3-5步)
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第5张图片


3. 为开发模式与发布模式指定不同的打包入口

Vue项目的开发模式和发布模式默认公用一个打包的入口文件,即main.js,但是不同开发模式下,入口文件内容可能会略不同,为了将开发过程和打包过程分离,需要配置不同的入口文件,
先将main.js复制一份并将两份分别命名为main-dev.js和main-prod.js,作为不同模式下的入口文件


4. configureWebpack 和 chainWebpack

配置不同的入口文件需要用这两种节点来定义webpack的打包配置
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第6张图片


5. 通过chainWebpack自定义打包入口

这里使用其中一种方法来配置入口文件
具体完整代码(包含发布模式下加载CDN资源和定制首页内容)

module.exports = {
    css: {
        extract: false
    },
    chainWebpack: config => {
        // 发布模式 设置入口文件目录
        config.when(process.env.NODE_ENV === 'production', config => {
            config
                .entry('app')
                .clear()
                .add('./src/main-prod.js')
		// 加载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
            })
        })
    }
}

6. 通过externals加载外部CDN资源

默认情况下,通过import语法导入的第三方依赖包,最终会被合并到同一个文件中,从而导致打包成功后,文件体积过大问题。
因此为了解决这种问题,可以通过webpack的externals节点,来配置加载外部的CDN资源,凡是声明在externals中的第三方依赖包,都不会被打包。

  1. 如第五步代码中,将
config.set('externals', {
                vue: 'Vue',
                'vue-router': 'VueRouter',
                axios: 'axios',
                lodash: '_',
                echarts: 'echarts',
                nprogress: 'NProgress',
                'vue-quill-editor': 'VueQuillEditor'
            })

添加到vue.config.js配置文件中

  1. 将main-prod.js中导入的插件的css样式表删除,并在index.html中导入

index.html文件的完整代码(包含Element UI 和定制首页内容)

<!DOCTYPE html>
<html lang="en">

<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>

    <% 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.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.8.2/theme-chalk/index.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/[email protected]/dist/vue-quill-editor.js"></script>

        <!-- element-ui 的 js 文件 -->
        <script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js"></script>

        <% } %>
</head>

<body>
    <noscript>
      <strong>We're sorry but vue_shop 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>

7. 通过externals优化Element UI的打包

  1. 在main-prod.js中,注释掉element-ui按需加载的代码
    【vue-cli】vue_shop电商后台管理项目优化,项目上线_第7张图片

  2. 在index.html的头部区域中,通过CDN加载element-ui的js和css样式,完整代码见第六步代码


8. 首页内容定制
不同的打包环境下,首页内容可能会有所不同,可以通过插件的方式来定制首页内容,例如不同的首页标题title
在vue.config.js文件中对插件进行配置,见第五条中的内容定制代码,
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第8张图片
然后在index.html首页中渲染,见第六步中定制内容代码

【vue-cli】vue_shop电商后台管理项目优化,项目上线_第9张图片


9. 路由懒加载
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第10张图片

  1. 在开发依赖中安装
  2. 在babel.config.js中配置插件
// 这是项目发布阶段需要用到的 babel 插件
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'
            }
        ],
        // 发布产品时候的插件数组
        // 移除发布阶段的console
        ...prodPlugins,
        // 配置路由懒加载
        '@babel/plugin-syntax-dynamic-import'
    ]
}
  1. 对router文件下的index.js的路由全部进行按需改造
import Vue from 'vue'
import VueRouter from 'vue-router'
// 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')


// import Cate from './components/goods/Cate.vue'
const Cate = () =>
    import ( /* webpackChunkName: "Cate_Params" */ '../components/goods/Cate.vue')

// import Params from './components/goods/Params.vue'
const Params = () =>
    import ( /* webpackChunkName: "Cate_Params" */ '../components/goods/Params.vue')


// import GoodsList from './components/goods/List.vue'
const GoodsList = () =>
    import ( /* webpackChunkName: "GoodsList_Add" */ '../components/goods/List.vue')

// import Add from './components/goods/Add.vue'
const Add = () =>
    import ( /* webpackChunkName: "GoodsList_Add" */ '../components/goods/Add.vue')


// import Order from './components/order/Order.vue'
const Order = () =>
    import ( /* webpackChunkName: "Order_Report" */ '../components/order/Order.vue')

// import Report from './components/report/Report.vue'
const Report = () =>
    import ( /* webpackChunkName: "Order_Report" */ '../components/report/Report.vue')


Vue.use(VueRouter)

const routes = [
    { path: '/', redirect: '/login' },
    { path: '/login', component: Login },
    {
        path: '/home',
        component: Home,
        //  进入home时 重定向welcome
        redirect: '/welcome',
        children: [
            { path: '/welcome', component: Welcome },
            { path: '/users', component: Users },
            { path: '/rights', component: Rights },
            { path: '/roles', component: Roles },
            { path: '/categories', component: Cate },
            { path: '/params', component: Params },
            { path: '/goods', component: GoodsList },
            { path: '/goods/add', component: Add },
            { path: '/orders', component: Order },
            { path: '/reports', component: Report }
        ]
    }
]

const router = new VueRouter({
    routes
})

// 挂载路由导航守卫
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

懒加载总结:
开发依赖中下载懒加载插件,在babel.config.js中配置懒加载插件,将路由文件中的按需修改路由,完成!


3. 项目上线

【vue-cli】vue_shop电商后台管理项目优化,项目上线_第11张图片


1. 通过node创建web服务器
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第12张图片
创建文件夹vue_shop_server,
初始化包管理配置文件 npm init -y,
安装express npm i express -S,
将dist文件复制到vue_shop_server文件夹中,
新建文件app.js入口文件内容如下(包含gzip压缩,和配置https服务):

const express = require('express')
const compression = require('compression')
const https = require('https')
const fs = require('fs')
const app = express()

const options = {
    cert: fs.readFileSync('./full_chain.pem'),
    key: fs.readFileSync('./private.key')
}

// 一定要把这一行代码,写到 静态资源托管之前 gzip压缩
app.use(compression())
app.use(express.static('./dist'))

app.listen(80, () => {
    console.log('server running at http://127.0.0.1')
})

// https.createServer(options, app).listen(443)

配置完成,在终端使用node ./app.js运行,在浏览器输入127.0.0.1可以访问


2. 开启gzip配置
压缩文件
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第13张图片


3. 配置HTTPS服务
在这里插入图片描述
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第14张图片
建议使用多域名通配符
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第15张图片


4. 使用pm2管理应用

解决关闭终端窗口就会退出服务器的问题。
在cmd中安装
然后可以再各终端中使用
【vue-cli】vue_shop电商后台管理项目优化,项目上线_第16张图片

你可能感兴趣的:(【vue-cli】vue_shop电商后台管理项目优化,项目上线)