gulp部署前端项目,以及.env文件的使用
本文介绍如何使用gulp作为工具帮我们自动化部署前端代码到后端服务器,以及如何使用.env文件来管理环境变量,管理不同环境的账密。
1 背景
在开发过程中,经常会需要把代码部署到开发或者测试环境,如果每次都需要手动打包好再拷贝到服务器,那就太麻烦了。先说一下部署的过程:连接服务器,然后把我们的代码上传到服务器指定位置。建一套部署工具,自动实现打包部署,可以省很多事,还不容易出错。
2 实现简易部署
2.1 安装依赖
npm i gulp gulp-sftp-up4 --save-dev
2.2 配置gulp
首先,在项目根目录下新建gulp.js,新建一个test-deploy的gulp task
const gulp = require("gulp"); const sftp = require("gulp-sftp-up4"); gulp.task("test-deploy", function() { return gulp.src("dist" + "/**").pipe( sftp({ host: "服务IP", user: "账户", pass: "密码", port: "端口 默认值是22", remotePath: `文件放置的路径` }) ); });
2.3 配置命令
在package.json中的scripts下添加命令 "test-deploy": "vue-cli-service build && gulp test-deploy"
2.4 测试部署
在控制台输入 npm run test-deploy
即可自动打包,部署,没出意外的话,可以在服务器对应的目录下看到刚刚上传的文件。没有线上服务器的话,可以用虚拟机试试。
简易的部署就到这里结束了。
在上面的部署中,我们把服务器的账户和密码都写在了gulp.js中,这个文件会被提交到git,这样是非常不安全的,所以接下来会介绍如何使用.env文件管理环境变量和账密,这适合用于有多个环境的管理,如果觉得太麻烦的话,也可以直接用 .ftppass 文件,它是gulp-sftp的配置文件。
3 .env文件的使用
3.1 新增.env文件
在根目录下新增 .env.dev 和.env.prod 两个环境文件,文件中会放除了账号密码之外的其他环境配置,比如
HOST = 192.168.2.88
REMOTE_PATH = /web-dev
3.2 新增.env.local文件
在根目录下新增 .env.dev.local 和.env.prod.local .local文件中的配置会和之前的配置做一个Object.assign的操作,.local文件用来存放账密,.local文件不会被提交到git上,而是在本地存放(为了示例完整,我会放上github),现在在本地可以看到四个.env文件
3.3 新增env.config.js
根目录下新建一个文件夹builder,新建文件env.config.js,里面的代码如下
const glob = require("glob"); const fs = require("fs"); const dotenv = require("dotenv"); const gutil = require("gulp-util"); const argv = Object.assign({ mode: null }, gutil.env); //列出.local文件,用于第一步询问需要部署哪个环境 const listLocal = glob.sync(".env.*.local").map(i => { const [lenPrefix, lenSuffix] = [".env.".length, ".local".length]; return i.substr(lenPrefix, i.length - lenSuffix - lenPrefix); }); //把env文件中的设置的参数放入process.env const setEnv = mode => { let envSetting = getEnv(mode); Object.keys(envSetting).forEach( _key => (process.env[_key] = envSetting[_key]) ); }; //合并.local文件, 比如合并 .env.dev 和 .env.dev.local, .local文件的配置会覆盖前面的 const getEnv = mode => { let data = [`.env.${mode || ""}`, `.env.${mode || ""}.local`]; console.log("data11", data); data = data.filter(i => fs.existsSync(i)); console.log("data", data); data = data.map(i => dotenv.config({ path: i }).parsed); return Object.assign.apply(this, data); }; module.exports = { mode: argv.mode, listLocal, getEnv, setEnv };
3.4 修改task deploy方法
在builder目录下,新增task-deploy.js文件
文件中引入了一个prompt包,在我们执行npm deploy之后,会询问要部署的环境,如下图
选择好要部署的环境后(chooseEnviroments),就会开启批量部署流程(batchDeploy),根据需要部署的环境,执行打包命令和上传到对应位置,批量部署完成后,则本次部署完成
const { execSync } = require("child_process"); const prompts = require("prompts"); const gulp = require("gulp"); const sftp = require("gulp-sftp-up4"); //deploy task const taskDeploy = ({ listLocal, setEnv, mode }, _callback) => { if (mode !== null) { return Promise.resolve() .then(() => console.log(`Deploy starting...`)) .then(() => setEnv(mode)) // 设置环境变量 .then(() => { return buildApp({ mode }); //打包项目 }) .then(() => { return deploy(); }) .catch(_error => console.log(`x ${_error.message && _error}`)) .finally(_callback); } else { // 没有指定打包环境,就执行下面这段代码,下面这段代码的实际作用就是根据命令行中的选择,构建出每个环境最终的gulp deploy task命令, // 执行命令的时候,因为mode不为空了,就会执行上面if中的代码了 chooseEnviroments({ envs: listLocal }) .then(({ environments }) => batchDeploy({ environments })) .catch(_error => console.log("error", _error)) .finally(_callback); } }; //使用prompts,在部署过程中提供友好的交互式命令行提示 const chooseEnviroments = ({ envs }) => { return prompts([ { type: "multiselect", name: "environments", message: "Which environments do you want to deploy?", choices: envs.map(i => ({ title: i, value: i })), validate: environments => environments.length === 0 ? "environments is required" : true } ]); }; //循环获取之前选择要部署的环境,挨个部署这些环境,这里如果不需要分环境打包,可以优化一下不用重复打包 const batchDeploy = ({ environments }) => { let envDeploySuccess = []; environments.forEach(_env => { let cmd = `gulp deploy --mode ${_env}`; let execResult = execCommandSync(cmd).toString(); console.log(execResult); if (execResult.includes("Deploy Succeeded")) envDeploySuccess.push(_env); console.log("exec", cmd, "done"); }); }; //执行gulp deploy task const execCommandSync = _cmd => { console.log("exec command:", _cmd); try { return execSync(_cmd) .toString() .trim(); } catch (e) { return null; } }; // 使用 vue cli 编译打包项目 const buildApp = ({ environment }) => { console.log(`Vue Cli Building for ${environment} ...`); let execResult = execCommandSync( `vue-cli-service build --mode ${environment}` ).toString(); console.log(execResult); return Promise.resolve(); }; //使用sftp上传文件到服务器 const deploy = () => { gulp.src("dist" + "/**").pipe( sftp({ host: process.env.HOST, user: process.env.USER, pass: process.env.PASSWORD, port: "22", //默认值就是22 remotePath: process.env.REMOTE_PATH }) ); }; module.exports = { taskDeploy };
3.5 gulp.js使用 taskDeploy,配置package.json
gulp.js使用 taskDeploy
gulp.task("deploy", _callback => taskDeploy(envConfig, _callback));
配置package.json,在scripts下添加
"deploy": "gulp deploy"
可以为某个环境单独配置一条命令
"deploy-dev": "gulp deploy --mode dev"
结语
利用.env文件,还可以实现一些个性化的部署,比如为某个环境打包专属的element theme。文章到这里就结束了,欢迎在留言区分享一下大家的部署方式,有用的话请点个赞,代码放在了github:https://github.com/daisygogogo/gulp-deploy-demo