Vue-CLI-2.x全家桶架構,支援打包後自動部署到伺服器構建案例

易在掘金發表於2019-05-05

今天有時間分享一些平時自己開發上的一些構建配置,我們以Vue-CLI-2.x來構建開發環境。 好,我們先來看一下我們要做哪些工作。

現附上原始碼地址,github.com/749264345/V…

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~ 原始碼地址,github.com/749264345/V… 如有更優的配置方案請求在下方留言~

相關文章