工程化实践指南

最后更新于:2022-04-02 05:26:34

[TOC] ## 前言 相信在前面工程化探索中已经对它有了一定的了解,那么我们在企业实践或者项目实践中应该如何实现呢?基于我们探索阶段所确定下来的策略。首先我们要有一个规范的文档目录,然后运用gulp构建工具来实现。 ## 项目初始化 ### npm包管理 我们需要package.json 来记录包文件的依赖模块。可以通过cnpm init 来实现初始化包文件,不过为了方便,我们给大家提供了package.json的模板文件,里面主要包括了gulp构建的基本依赖以及构建目录的基本依赖。通过上述的包文件你可以实现快速引入基本依赖模块,通过命令行` cnpm i --save-dev`,也为gulp构建做了初步的准备工作。 为大家准备了模板标准化项目: [fe-stand](https://github.com/csnikey/fe-stand.git) ,可以通过这个项目快速新建你所需的目录结构。 ## 前端组件化方案 * 组件化可视化后台管理 组件化的技术选型,可以可视化的看到所有的项目组件,支持登录注册,运用了野狗云的服务。 * [组件库汇总地址,账号csnikey/qq123789](http://refined-x.com/WidgetsPlayground) * [组件库源码地址](https://github.com/tower1229/WidgetsPlayground) ## 代码规范化 ### 借助editor.config 规范编辑器排版 * [editorConfig 简书](https://www.jianshu.com/p/712cea0ef70e) * [EditorConfig官方配置大全](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties) ### 借助eslint 规范项目代码 ### 借助脚手架规范项目结构 ### 借助设计模式规范开发模式 ## 自动部署 ### CI/CD 流程 ci continuous integration 持续集成的意思 当你做一件事情的时候 可以吧重复的命令行交给工具去做 这个就叫持续构建集成 原理:每次提交代码到github之后 自动检测代码的部分 ,生成linux虚拟机 ,运行你设置的命令,通过这些命令来进行测试 构建等工作 比如hexo g hexo d等 ,自动生成页面 部署页面等 1 本地机器上写代码提交代码 2 push 到 git 远程仓库git hook 触发 jenkins 的构建 job (自动) 3 jenkins job 中拉取项目代码,运行 npm run unit 和 npm run build,如果失败,发送邮件通知相关人。(自动) 4 jenkins job 中执行测试服务器的部署脚本 (自动) 在 CI/CD 流程中,只有步骤1和步骤2需要人工操作,其他步骤都是自动运行,是一个非常标准化的流程,减少了人工操作的风险,省去了重复性工作,增强了项目的可见性。接下来我们将通过配置 jenkins 和 gitlab webhook 来实现这个流程。 **备注:** 如何设置webhook可以参考我另一篇文章[webhook设置](http://doc.damobing.com/fepro/477811) ### gulp为载体的任务模型 #### 通用配置文件 ~~~ var config = { stable:{ host:"10.0.0.36", port:"80", user:"root", pass:"xxxx@123", remotePath:"/home/xx" }, sit:{ host:"10.0.0.231", port:"80", user:"root", pass:"xxxxroot", remotePath:"/home/xx" }, dist:"./dist/" } ~~~ #### 打印任务信息 ~~~ var chalk=require("chalk"); function printMsg(type){ let str=`文件开始上传到` switch(type){ case "stable":str+=`stable环境:10.0.0.36`; break; case "sit" :str+=`sit环境:10.0.0.231`; break; } console.log(chalk.yellow('--------------------------------------------------')); console.log(chalk.green(str)); console.log(chalk.green(`资源路径:${config[type].remotePath}`)); console.log(chalk.yellow('--------------------------------------------------')); } ~~~ #### 借助shell ,通过scp,rsync实现本地文件部署 * scp的方式 可以覆盖同名文件,其他的用途暂未开发,有兴趣的可以自行增加。 [run-sequence模块介绍](https://npm.taobao.org/package/run-sequence) [scp菜鸟教程](http://www.runoob.com/linux/linux-comm-scp.html) ~~~ //run-sequence按照指定顺序执行task任务 var runSequence = require('run-sequence'); gulp.task('deploy:dev', ['build:dev'], function(){ function finishedDisplay(){ console.log(chalk.yellow('--------------------------------------------------')); console.log(chalk.yellow(' 文件已经上传到开发服务器 ')); console.log(chalk.yellow(' 资源路径:http://static.stable.ikuko.com/h5/ ')); console.log(chalk.yellow('--------------------------------------------------')); } runSequence( 'deploy:scp:dev', finishedDisplay ); }) gulp.task('deploy:scp:dev', shell.task([ 'scp -r ' + config.basePath.dev + '/* root@10.0.0.36:/home/web/ikuko_static/h5', ])) ~~~ * rsync的方式 [rsync参考资料](https://www.cnblogs.com/f-ck-need-u/p/7220009.html) [rsync简明教程](http://waiting.iteye.com/blog/643171) [rsync排除文件详解](https://www.cnblogs.com/zl1991/p/7232991.html) 如果你不想删除远程的文件夹内容,可是吧--delete删除。 **备注1:** 使用rsync一定要注意的一点是,源路径如果是一个目录的话,带上尾随斜线和不带尾随斜线是不一样的,不带尾随斜线表示的是整个目录包括目录本身,带上尾随斜线表示的是目录中的文件,不包括目录本身。 **备注2 :** 如果你想排除某些文件,可以使用--exclude="xx.file",这个只能排除某个或者某些匹配规则的文件(这里的文件路径是目标目录的相对路径),如果你需要排除的是多个的,需要写多个--exclude,如果你需要的是一个排除的列表,建议你写到一个匹配规则文件里,比如--exclude-from=”/exclude.list”,这里列表文件的路径是本地源目录的绝对路径,里面写的文件路径还是目标服务器目录相对路径。 ~~~ var shell=require("gulp-shell"); gulp.task("deploy:stable",shell.task([ `rsync -e "ssh -p22" -avpz --delete ./dist/ root@${config.stable.host}:${config.stable.remotePath}` ])) ~~~ #### 通过gulp task实现任务部署(这里推荐gulp-sftp,rsync两种) * gulp-sftp 具体模块介绍:[gulp-sftp](https://npm.taobao.org/package/gulp-sftp) 备注:目前这种方法可以实现上传覆盖同名文件,但是不能清空原有的文件,在官方的最新开发分支中可以通过clearDestination来实现清空原来的文件,目前还不能实现,这种方案的好处就是可以不用输入密码。 ~~~ //载入模块 var gulp = require('gulp'); var sftp = require('gulp-sftp'); var chalk = require("chalk"); gulp.task('deploy:stable', function () { // 这里的源目录与rsync的解析是不同的哦 return gulp.src("./dist/**/*") .pipe(sftp({ host: config.stable.host, user: config.stable.user, pass: config.stable.pass, remotePath:config.stable.remotePath, callback:printMsg("stable"), })); }); ~~~ * gulp-rsync 具体模块介绍:[gulp-rsync](https://npm.taobao.org/package/gulp-rsync) 这种方案可以实现吧原来的文档目录清空并且传入新的本地文档,可以支持覆盖同名文件,不好的地方就是需要输入一次密码,如果不想删除远程文件,可以吧emptyDirectories设置为false(true的时候原来的文件根目录下有的多余的时间不会被删除) ~~~ var rsync = require("gulp-rsync"); gulp.task('deploy:stable', function () { return gulp.src(config.dist) .pipe(rsync({ root:"dist", hostname: config.stable.host, username: config.stable.user, archive:true, recursive: true, destination:config.stable.remotePath, progress:true, emptyDirectories: true, clean:true })); }); ~~~ #### gulp最终方案 ~~~ var gulp = require('gulp'); var chalk = require("chalk"); var shell = require("gulp-shell"); // env:stable sit 打印对应环境的信息 function printMsg(type){ let str=`文件已经上传到` switch(type){ case "stable":str+=`stable环境:10.0.0.36`; break; case "sit" :str+=`sit环境:10.0.0.231`; break; } console.log(chalk.yellow('--------------------------------------------------')); console.log(chalk.green(str)); console.log(chalk.green(`资源路径:${config[type].remotePath}`)); console.log(chalk.yellow('--------------------------------------------------')); } gulp.task("deploy:rsync:stable", shell.task([ `rsync -e "ssh -p22" -avpz --delete ./dist/ root@${config.stable.host}:${config.stable.remotePath}` ]) ) // 上传到stable环境 gulp.task('deploy:stable',['deploy:rsync:stable'], function () { printMsg("stable") }); gulp.task("deploy:rsync:sit", shell.task([ `rsync -e "ssh -p22" -avpz --delete ./dist/ root@${config.sit.host}:${config.sit.remotePath}` ]) ) // 上传到sit环境 gulp.task('deploy:stable',['deploy:rsync:sit'], function () { printMsg("sit") }); ~~~
';