美文网首页
Vue-CLI-2.x全家桶架构,支持打包后自动部署到服务器构建

Vue-CLI-2.x全家桶架构,支持打包后自动部署到服务器构建

作者: 什么都稳了 | 来源:发表于2019-05-05 17:28 被阅读0次

    今天有时间分享一些平时自己开发上的一些构建配置,我们以Vue-CLI-2.x来构建开发环境。
    好,我们先来看一下我们要做哪些工作。
    现附上源码地址,https://github.com/749264345/Vue-CLI-2.x

    1.Vue,Vuex,vue-router,axios通过CDN引入;优化打包后文件过大的问题
    2.开发环境区分开发,测试,生产;提高开发效率
    3.打包区分测试与生产
    4.实现项目打包后自动部署到远程服务器
    5.模块化构建vuex状态管理
    6.打包后自动清除console.log()
    7.项目默认基于Element-ui,对相关组件二次封装
    8.模块化构建axios请求响应拦截器

    一寸光阴一寸金,寸金难买寸光阴~
    废话不多说,直接撸起袖子就是干~~

    1.Vue,Vuex,vue-router,axios通过CDN引入

    在过去我们都习惯使用npm或者cnpm安装依赖,因为这种操作非常方便,但是有利必有弊,有些小伙伴在将项目打包后会发现打包后的js文件非常庞大,有些甚至达到了几兆,所以最终导致应用打开时首屏加载非常慢,因此我们可以使用传统的引入方式,也就是CDN引入。
    Vue,Vuex,vue-router,axios,这些均为静态资源,我们从它们官网下载适合的版本后放入项目根目录【static】文件夹,然后修改几个地方:
    首先,index.html

        <!--兼容ie-->
        <script src="./static/libs/polyfill.min.js"></script>
        <script src="./static/libs/eventsource.js"></script>
        <!--vue-->
        <script src="./static/libs/vue.js"></script>
        <script src="./static/libs/vue-router.min.js"></script>
        <script src="./static/libs/element-ui/element-ui.js"></script>
        <script src="./static/libs/axios.js"></script>
        <script src="./static/libs/vuex.js"></script>
    

    然后修改,build/webpack.base.conf.js

    module.exports = {
        externals: {
            'vue': 'Vue',
            'vuex': 'Vuex',
            'vue-router': 'VueRouter',
            'axios': 'axios'
        },
        ...
    }
    

    到这里基本配置已经完成,最后一步需要在main.js中删除原先对这些模块的import操作即可。这样后再打包项目,你会发现页面非常丝滑,几乎秒开。

    2.开发环境区分开发,测试,生产;提高开发效率

    在调试接口,或者debug的时候我们经常会切换环境,而且在打包的时候又要改成生产的接口,这样没有效率,所以我们可以做如下配置。
    在config/dev.env.js文件中,

    const TARGET = process.env.npm_lifecycle_event;
    
    //开发环境
    if (TARGET === 'dev') {
        var data = {
            NODE_ENV: '"dev"',
            API: '"http://www.dev.com"'
        }
    }
    
    //测试环境
    if (TARGET === 'test') {
        var data = {
            NODE_ENV: '"test"',
            API: '"http://www.test.com"'
        }
    }
    
    //生产环境
    if (TARGET === 'prod') {
        var data = {
            NODE_ENV: '"prod"',
            API: '"http://www.prod.com"'
        }
    }
    

    我们从process.env.npm_lifecycle_event中获得当前node执行的环境来区分项目运行的环境,这样我们可以用来区分接口环境,因此我们添加相关指令。
    在根目录package.json文件中,

      "scripts": {
        "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
        "test": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
        "prod": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js"
      },
    

    添加三条指令,分别为dev,test,prod对应config/dev.env.js文件中添加的三个环境。
    到这里我们完成了开发环境的区分。

    3.打包区分测试与生产

    原理和上面一致,
    在config/prod.env.js文件中,

    const TARGET = process.env.npm_lifecycle_event;
    
    //测试环境
    if (TARGET === 'build:test') {
        module.exports = {
            NODE_ENV: '"build:test"',
            NODE_NAME: '"测试"',
           API: '"http://www.test.com"'
        }
    }
    
    //生产环境
    if (TARGET === 'build:prod') {
        module.exports = {
            NODE_ENV: '"build:prod"',
            NODE_NAME: '"生产"',
            API: '"http://www.prod.com"'
        }
    }
    

    同时在根目录package.json文件中,

      "scripts": {
        "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
        "test": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
        "prod": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
        "build:test": "node build/build.js",
        "build:prod": "node build/build.js"
      },
    

    我们看到添加了最后2条指令,这里我么就可以直接打测试包,与生产包。
    而不需要每次在项目中修改代码。

    4.实现项目打包后自动部署到远程服务器

    首先安装

    npm install scp2 --save-dev
    

    然后修改项目build/build.js
    添加如下代码,

    var scpClient = require('scp2');
    var serverConf = require('../config/prod.env');
    const spinner2 = ora('正在发布到' + serverConf.NODE_NAME + '服务器...');
    spinner2.start();
    scpClient.scp('dist/', serverConf.server,
        function (err) {
            spinner2.stop();
            if (err) {
                console.log(chalk.red('发布失败.\n'));
                throw err;
            } else {
                var date = new Date();
                var year = date.getFullYear();
                var month = date.getMonth() + 1;
                var day = date.getDate();
                var hour = date.getHours();
                var minute = date.getMinutes();
                var second = date.getSeconds();
                console.log(chalk.green(
                    'Success! 成功发布到' + serverConf.NODE_NAME + '服务器! \n' +
                    year + '年' + month + '月' + day + '日 ' + hour + ':' + minute + ':' + second
                ));
            }
        }
    );
    

    另外,我们添加了发布后显示当期时间的功能,方便我们查看。
    我们远程服务器的配置信息放在在config/prod.env.js文件中,如下,

    //测试环境
    if (TARGET === 'build:test') {
        module.exports = {
            NODE_ENV: '"build:test"',
            NODE_NAME: '"测试"',
            API: '"http://192.168.1.123:8080"',
            server: {
                host: '192.168.1.123',
                port: 3122,
                username: 'root',
                password: '2019111',
                path: '/usr/local/nginx/html/test'
            }
        }
    }
    

    到这里我们完成了,自动部署的功能,命令行输入

    npm run build:test
    
    image.png

    稍等片刻,


    image.png

    OK,完美~

    5.模块化构建vuex状态管理

    由于篇幅,以及对于vuex的配置有很多,这里不再做阐述。

    6.打包后自动清除console.log()

    打开build/webpack.prod.conf.js添加一个插件,

    plugins:[
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: {
              warnings: false,
              drop_console: true,
              pure_funcs: ['console.log']
            }
          },
          sourceMap: config.build.productionSourceMap,
          parallel: true
        }),
    ]
    

    这样,项目打包后的console.log()将不会出现在控制台,很干净。

    7.项目默认基于Element-ui,对相关组件二次封装

    这里我们以element-ui分页组件为例,
    我们新建一个vue文件,

    <template>
        <el-pagination background style="text-align:right;margin-top:10px;" popper-class="pagination"
            layout="total,  prev, pager, next,sizes, jumper"
            :total="total" 
            :page-sizes="[10, 20, 30, 40,50]"
            :page-size="size"
            :current-page="current"
            @size-change="sizeChange"
            @current-change="currentChange"></el-pagination>
    </template>
    <script>
    export default {
        data() {
            return {
                pageSize: this.size,
                pageCurrent: this.current
            }
        },
        props: {
            total: {
                type: Number,
                default: 0
            },
            current: {
                type: Number,
                default: 1
            },
            size: {
                type: Number,
                default: 10
            }
        },
        methods: {
            currentChange(current) {
                this.pageCurrent = current;
                this.emit();
            },
            sizeChange(size) {
                this.pageSize = size;
                this.pageCurrent = 1;
                this.emit();
            },
            emit() {
                this.$emit('pageChange', {
                    pageSize: this.pageSize,
                    pageCurrent: this.pageCurrent
                })
            }
        }
    }
    </script>
    

    我们通过emit()方法将组件内的状态发送给父组件,父组件通过事件订阅来监听,我们来看父组件,

    <script>
    <template>
    <!-- 分页 -->
    <Pagination v-on:pageChange="pageChange" :total="total" :current="pageCurrent" :size="pageSize"></Pagination>
    </template>
    
    //引入组件
    import Pagination from "../components/Pagination";
    
    export default {
        components: {
            Pagination
        },
        data() {
            return {
                //分页数据
                total: 0,
                pageSize: 10,
                pageCurrent: 1
            };
        },
        methods: {
            //分页发生改变
            pageChange(res) {
                this.pageSize = res.pageSize;
                this.pageCurrent = res.pageCurrent;
            }
        }
    };
    </script>
    

    我们使用pageChange()来监听,这样不论是代码篇幅还是逻辑都变得更清晰。

    8.模块化构建axios请求响应拦截器

    我们新建一个文件,interceptors.js

    // 接口请求拦截器
    axios.interceptors.request.use((config) => {
            //每次请求发起前为当前接口创建,取消请求的实例
            const CancelToken = axios.CancelToken;
            const source = CancelToken.source();
            Vue.prototype.$requestCancel = function () {
                source.cancel('canceled');
            };
            config.cancelToken = source.token;
            // 接口添加头信息
            config.headers.Authorization = localStorage.getItem('token');
            return config;
        },
        (err) => {
            return Promise.reject(err);
        }
    );
    
    // 接口响应拦截器
    axios.interceptors.response.use((response) => {
         if (response.data.code == 200) {
             localStorage.setItem('token', response.headers.authorization);
          } else {
              Vue.prototype.$message.error(response.data.msg);
          }
            return response;
        },
        (error) => {
            return Promise.reject(error.response.data);
        }
    );
    
    

    我们通过拦截器实现token信息的统一获取和请求携带,统一提示错误信息,并且记录当前请求,并且在路由跳转时取消上一张页面的请求,提高当前页面的有效展现。

    由于篇幅问题,具体其他配置请移步我的github~
    源码地址,https://github.com/749264345/Vue-CLI-2.x
    如有更优的配置方案请求在下方留言~

    相关文章

      网友评论

          本文标题:Vue-CLI-2.x全家桶架构,支持打包后自动部署到服务器构建

          本文链接:https://www.haomeiwen.com/subject/gahcoqtx.html