工程化实践指南
最后更新于: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")
});
~~~
';