本系列文章共分为基础篇,安全篇,拓展篇。
曾几何时,我相信部分 Web Developer (包括我)使用的项目发布方式比较传统(使用 xftp 或者 sublime text 的插件 sftp 等),发布方式简单又粗暴,想发布哪个目录就直接上传覆盖...
但是这种方式对于现在的前端项目有些弊端:
若项目包含 webpack\gulp 等构建工具,则每次发布都需要等待构建完成后再手动上传,效率低;
若项目为前端的服务端渲染项目,例如 vue 的服务端渲染,那么项目上传服务器后还得登录服务器重启进程;
发布时由于选错文件或者选错发布环境导致的上传(>﹏<)悲剧,可没有后悔药吃。
我知道你想告诉我还可以使用 git webhook 等自动化工具,的确这是一种比较高级的用法,也非常可靠,但是搭建过程对于新手还是比较麻烦的,而且前端还是不太同于服务端,前端项目大多需要构建,那么构建过程究竟放在服务端还是本地,这是一个问题。
我理想中的发布器应该是易于搭建,通过配置文件就能选择发布到不同的环境,敲完一行发布命令就可以去泡杯茶,让它自己完成整个发布流程。
于是,fjpublish就诞生了。它是一个不同于 git webhook 的发布思路,基于 nodejs 的能力自动化整个发布流程,顺便把 git 提交一下...
如果你已经安装了 nodejs (6.0+),那么只需要一个命令就能完成 fjpublish 的安装
npm install fjpublish -g
全局安装就可以在任意路径下使用 fjpublish 这个命令了。 注意: fjpublish 依赖一份配置文件,默认是 fjpublish.config.js ,如果不想在版本库中提交服务器安全信息,请千万记得把它加入忽略文件中,如.gitignore
fjpublish 命令行默认会读取当前工作目录下的fjpublish.config.js文件,该文件返回一个对象,举例结构如下:
module.exports = {
//modules 开始
modules: [{
name: '测试环境', //标识要发布的环境描述
env: 'test', //发布环境的唯一标识
ssh: {
host: '12.23.345.678', //远程服务器 ip
username: 'root', //登录服务器的用户名
//rc 版本的 user 选项和 userName 选项请在未来统一配置为 username
password: '12345678', //登录服务器的密码
},
buildCommand: 'build', //要进行构建的命令 build => npm run build
localPath: 'example', //项目中要发布的目录
remotePath: '/www/example', //项目中要发布到远程服务器的目录
tag: '123' //标注发布的版本,可不设置
}, { ... }],
//modules 结束
nobuild: true, //modules 外的字段可用于每一个 module 继承,这里仅用于举例
tag: 'v1', //modules 外的字段可用于每一个 module 继承,这里仅用于举例
}
以上展示了一个简单的配置,关于使用 fjpublish 和阅读本文档,还需明白以下几个概念:
modules 数组中每一个对象(也称module)代表一个发布环境,在本文档中module指在配置文件中任意一个环境配置 module
在本文档中config指代 module.exports 输出的所有字段(包含 modules 在内)的对象。
config中 modules 字段外的字段在初始后将并入每一个module,优先级为module > config,也可以理解为module继承自config。
config中 modules 字段外的字段不仅仅为了继承给module 实例也可以是为了定义某些全局的配置字段。
听起来好像一头雾水,建议看完例子再重新理解以上内容
让我们闲话少说,先上几个例子来了解 fjpublish 能做什么。
发布一个项目文件到远程环境,并备份旧文件。
// 项目根目录下 fjpublish.config.js
module.exports = {
modules: [{
name: '测试环境',
env: 'test',
ssh: {
host: '192.168.0.xxx',
username: 'root',
//rc 版本的 user 选项和 userName 选项请在未来统一配置为 username
password: 'xxxxxx',
},
buildCommand: 'webpack',
localPath: 'example',
remotePath: '/www/manman/test',
},{
name: '预发布环境',
env: 'pre_release',
//剩余配置参考‘测试环境’
},{
name: '正式环境',
env: 'pre_release',
//剩余配置参考‘测试环境’
}]
}
// 项目根目录下 package.json
// 用于使用构建命令 npm run webpack 来调用 webpack
...
"scripts": {
"webpack": "webpack --config example/webpack/build/build.js"
},
...
fjpublish env -s
可以使用命令fjpublish env <env> --diff
开启差异化发布,每次发布只上传有改动的文件,极大的缩短上传时间。
对于不需要构建的项目,不需要准备 package.json,并在配置文件中设置nobuild
选项;
nobuild: true
--nobuild
选项fjpublish env <env> --nobuild
有些时候我们的项目需要发布的文件夹不止一个,或者需要忽略某些文件,那么就需要调整发布方式。
使用module的localPathEntries
来发布多个目录;
使用module的localPathIgnore
忽略所有 txt 结尾的文件。
// 项目根目录下 fjpublish.config.js
module.exports = {
modules: [{
name: '测试环境',
env: 'test',
ssh: {
host: '192.168.0.xxx',
username: 'root',
//rc 版本的 user 选项和 userName 选项请在未来统一配置为 username
password: 'xxxxx',
},
buildCommand: 'webpack',
localPathEntries: ['example', 'lib'],
localPathIgnore: '**/*.txt',
remotePath: '/www/manman/multiple',
}],
}
fjpublish env test
localPath
和localPathEntries
会发生什么吧;...
localPath: 'example/webpack', //当 localPathEntries 存在时 localPath 可不填,不填意味着项目根目录
localPathEntries: ['build', 'dist'],
...
对于需要重启服务的项目,fjpublish 也是支持的。
使用module的配置项postCommands
在项目发布后重启 pm2 进程;
忽略当次构建过程并提交一次 git ;
使用module的配置项ssh2shell
设置每个远程命令超时时间为 20 秒。
// 项目根目录下 fjpublish.config.js
module.exports = {
modules: [{
name: '测试环境',
env: 'test',
ssh: {
host: '192.168.0.xxx',
username: 'root',
//rc 版本的 user 选项和 userName 选项请在未来统一配置为 username
password: 'xxxxxx',
},
ssh2shell: {
idleTimeOut: 20000
},
postCommands: ['pm2 reload xxx'],
buildCommand: 'build',
localPath: 'example',
remotePath: '/www/manman/test',
}]
}
fjpublish env test --nobuild --commit '远程后置命令'
有备份项目的功能那当然得有还原的办法啦。
tag
标记为‘自定义 tag 的版本’的版本;// 项目根目录下 fjpublish.config.js
module.exports = {
modules: [{
name: '预发布环境',
env: 'pre_release',
ssh: {
//略
},
localPath: 'example',
remotePath: '/www/zhangchao/pre_release',
}],
}
fjpublish recover pre_release
可以使用命令fjpublish recover pre_release -p, --previous
快速还原至上个版本而不需要选择;
可以使用选项recoverTemplate
自定义版本列表模板;
快速还原一样也会执行postCommands
配置的后置命令。
以上的例子描述了fjpublish中最基本的功能,fjpublish 也有强大拓展能力,感兴趣的童鞋可以直接移步官方文档了解更多,别忘了在 github 上给我点个star哦。
下一期我们将谈论如何使用 fjpublish 进行安全发布,拜拜∩__∩y。
fjpublish 官方交流群:608809145
1
bramblex 2017-11-18 13:00:33 +08:00
虽然这种轮子已经有很完善的, 不过造轮子不易, 给个 star 支持一下吧
|
4
ibegyourpardon 2017-11-18 15:53:29 +08:00
大多数轮子在造的时候可能还真没考虑过这个问题,就是前端和部分后端有一个特性差异在于,前端有个构建过程。
需要通过一个构建过程完成了,才能得到我要的可调式的工程代码(还不见得是最终在浏览器里执行的代码),这个构建过程放在哪里,本地跑还是服务器跑,各有利弊。 都用 hook 或者 git 的方式甩到服务器上去,让服务器做这件事当然可以,对源码的管理倒也变得简单了,但在调试的时候有麻烦多多。在本地构建的话,代码混杂,源码和构建编译后的代码发布过去的位置还不一样,还最好能统一在一套系统里一起做完。 这也是为啥大家总是找轮子却又总觉得别人的不尽如人意的原因之一,别人的总归很难那么好的适配到自己所用的那套流程里。 当然,等回头试完楼主这套东西,估计我也会参考下,然后再造个自己的轮子了。。。 |
5
manman51 OP @ibegyourpardon 相比而言,我喜欢把构建过程放在本地,也懒得折腾 webhook
|
6
zhlssg 2017-11-18 17:50:09 +08:00 via iPhone
从流程上来说,发布通过 webhook 自动构建还是省心的,如果从多人协作的角度,两种方式那种更优?
|
9
rashawn 2017-11-19 09:03:38 +08:00 via iPhone
还可以前端只用 js 写 更新的时候只需要把 js 更新到 cdn
|