内容简介:在上篇PS:只作为本人工作的分享,不作为任何形式的指南、教程、最佳实践等,也并非手把手系列以下内容请结合
在上篇 《【vue-cli3升级】老项目提速50%(二)》 文中,评论区好几个人对文中task任务以及 shell 打包推送远程仓库表示感兴趣,希望我多描述些内容... 基于此原因、在此基础上,谈一谈我在SPA项目打包 => 部署的工程化内容
PS:只作为本人工作的分享,不作为任何形式的指南、教程、最佳实践等,也并非手把手系列
项目环境描述
- SPA项目(Vue-cli3)
- Gitlab代码仓库
- node 10.8.0
- npm 6.5.0
- Nginx服务器
- Linux系统
- Jenkins持续集成部署工具
说下上篇文中Task.js、run.sh
以下内容请结合 《【vue-cli3升级】老项目提速50%(一)》 、 《【vue-cli3升级】老项目提速50%(二)》 阅读
为什么这么做?
结合实际场景罗列两个吧...
- 为了随时发布前端项目,不用等到晚上加班发布...
- 曾经,在发布过程中,老板正在浏览…然后白屏了…所以为了发布时线上用户无感知
整体流程(画图真墨迹啊)
-
执行
run.sh
,以beta
环境为例,项目根目录执行./run.sh beta
-
在
run.sh
中,初始化beta环境的远程仓库,拉取代码到本地.deploy/beta
目录,将.deploy/beta
目录中的文件复制到本地dist
目录 -
在
run.sh
中,执行构建:npm run build_beta
-
在
vue.config.js
中,创建版本号lastVersion
,将版本号lastVersion
加入到css
、js
资源文件名中(我是加在最前面的,位置随意,和task.js
中的正则对应) -
在
vue.config.js
中,注入task.js
,执行任务const task = require('./task') task.run(lastVersion) 复制代码
-
在
task.js
中,将版本号写入history.js
,判断是否超出最大值(最大5个历史版本),超出则执行rmFiles()
,删除本地dist
目录中最老的版本资源 -
复制本地
dist
目录文件到.deploy/beta
中,提交.deploy/beta
文件到远程仓库
附图:了解下.deploy/beta目录文件,history.js文件,远程Gitlab仓库代码
【Task.js】
前提:打包时不清除dist文件目录,以增量的形式打包。
vue-cli3下可参考 《【vue-cli3升级】老项目提速50%(二)》
vue-cli2下在 /build/build.js
中找到以下代码注释掉
// rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { // if (err) throw err // }) 复制代码
何时执行?build构建时
作用:利用nodeJs的fs模块操作history.js,存储最多5个版本,超过5个在本地dist目录中删除匹配最老版本的相关资源
代码(基本上都加上注释描述了)
const fs = require('fs') // node fs模块,操作文件 const path = require('path') // node path模块,操作路径 const endOfLine = require('os').EOL // node os模块,不同操作系统的行尾符 module.exports = { maxHistoryNum: 5, // 控制存储版本最大值 historyFile: path.resolve(__dirname, './dist/history.js'), // 本地dist目录中的history.js staticDir: path.resolve(__dirname, './dist/'), // 本地dist目录 // history.js不存在,创建 creataHistoryIfNotExist () { if (!fs.existsSync(this.historyFile)) { this.storeHistory([], 'a+') } }, // @done 将数据写到 history.js storeHistory (list, mode) { let historyFile = this.historyFile let outJson = 'module.exports = [' + endOfLine let listLen = list.length if (list && listLen > 0) { list.forEach((item, index) => { if (index === listLen - 1) { outJson += ` ${item}${endOfLine}` } else { outJson += ` ${item},${endOfLine}` } }) } outJson += ']' + endOfLine // 以 a+ 的falg标志在history.js写入和追加内容 fs.writeFileSync(historyFile, outJson, { flag: mode }) }, // 递归删除目录中的文件 (构建完成时版本>最大值时执行) rmFiles (dirPath, regexp) { let files try { files = fs.readdirSync(dirPath) } catch (e) { return } if (regexp && files && files.length > 0) { for (let i = 0; i < files.length; i++) { let filename = files[i] let filePath = dirPath + '/' + files[i] if (fs.statSync(filePath).isFile() && regexp.test(filename)) { console.log('删除过期的历史版本->(' + regexp + '):' + filename) fs.unlinkSync(filePath) } else { this.rmFiles(filePath, regexp) } } } }, // @done 更新history.js内容 cleanOldVersionFilesIfNeed (version) { let staticDir = this.staticDir let maxHistoryNum = this.maxHistoryNum let history = [] try { history = require(this.historyFile) } catch (e) { console.log(e) } // 加入最新的版本,老的的版本删除 history.push(version) // 如果历史版本数超过限制,则删除老的历史版本 let len = history.length if (len > maxHistoryNum) { let oldVersions = history.slice(0, len - maxHistoryNum) for (let i = 0; i < oldVersions.length; i++) { let ver = oldVersions[i] let reg = new RegExp(ver) this.rmFiles(staticDir, reg) } // 更新history文件 let newVersions = history.slice(len - maxHistoryNum) this.storeHistory(newVersions) } else { // 写入history文件 this.storeHistory(history) } }, // 入口 run (version) { this.creataHistoryIfNotExist() this.cleanOldVersionFilesIfNeed(version) } } 复制代码
【 run.sh 】
我们简单的分为beta(测试环境)和pro(线上环境)
作用:一键打包本地代码,提交上传至远程代码仓库
先看代码:
#!/bin/bash # 初始化上下文。有参数的 initContext(){ # dist目录 source_dir=dist # 获取参数,beta环境和pro环境 if [ $# -gt 0 ] && [ $1 = 'beta' ];then # beta环境远程仓库地址, git_url=git@beta/example.git # 本地根目录存放打包代码 dest=".deploy/beta" # npm 的脚本名,对应package.json定义的script node_script=build_beta else # pro环境远程仓库地址 git_url=git@pro/example.git # 本地根目录 dest=".deploy/pro" # npm 的脚本名,对应package.json定义的script node_script=build_pro fi } # 初始化git目录,pull最新代码 init(){ echo +++init start; if [ ! -d $dest ]; then git clone $git_url $dest fi # 记录现在的目录位置,pwd获取本地路径 cur=`pwd` # 进入git目录 cd $dest # git checkout . git add . git stash # reset为线上最新版本,要先pull一下再reset。 git pull origin master git reset --hard origin/master # 然后再pull一下 git pull origin master # 回到原来的目录 cd $cur echo ---init end; } # 重置dist目录 resetDist(){ echo +++resetDist start rsync -a --delete --exclude='.git' $dest/. ./dist echo ---resetDist end } # 构建 build(){ echo +++build start npm run $node_script echo ---build end } # 检查是否成功 checkBuild(){ if [[ ! -f $source_dir/index.html || ! -d $source_dir/static ]]; then echo error else echo ok fi } # 复制代码到$dest目录 cpCode(){ echo +++cpCode start # 复制代码,所有文件包含隐藏文件 rsync -r --delete --exclude='.git' $source_dir/. $dest echo ---cpCode end } # 提交到远程git仓库 commit(){ echo +++commit start # 记录现在的目录位置,最后要回来的 cur=`pwd` # 进入git目录 cd $dest # 提交的字符串 commit_str="commited in `date '+%Y-%m-%d_%H:%M:%S'`" git add . git commit -am "${commit_str}" git push origin master # 回到原来的目录 cd $cur echo ---commit end } # 显示帮助信息 help(){ # 微信h5版本 echo ----微信h5版本-------- echo ./run.sh build "#"构建代码 echo ./run.sh init "#"初始化git仓库 echo ./run.sh commit "#"提交到git echo ./run.sh "#"执行全部任务 echo ./run.sh hello "#"hello echo ./run.sh test "#"test echo ./run.sh beta "#"一键构建和提交beta版本 # app内嵌版本 echo ----app内嵌版本-------- echo ./run.sh app "#"一键构建和提交app版本 echo ----帮助信息-------- echo ./run.sh help "#"帮助 } # 测试用的 test(){ echo "a test empty task" } # 入口 if [[ $# -lt 1 || $1 = 'app' || $1 = 'beta' ]]; then # 无参数则打pro包,否则打相应类型的包 if [ $# -lt 1 ];then type=pro else type=$1 fi echo ===\>准备构建${type}版 initContext $type && init && resetDist # 构建代码 buildRes=$(build) # 检查构建结果 echo -e "$buildRes" if [[ $buildRes =~ "ERROR" ]]; then echo "$(tput setaf 1)xxx\>build error,task abort$(tput sgr0)" else # 代码构建成功才继续。 checkRes=$(checkBuild) if [ $checkRes == "ok" ];then cpCode && commit echo "$(tput setaf 2)===\>task complete$(tput sgr0)" else echo "$(tput setaf 1)xxx\>build error,task abort$(tput sgr0)" fi fi elif [ $1 ]; then # 参数不是包类型的,当中函数处理 echo ===\>准备执行${1}函数 initContext beta func=$1 $func echo ===\>task complete fi 复制代码
上篇文章评论区有人问到 rsync
,文中用来同步本地硬盘中的不同目录。可以看下这篇教程
Linux
系统已经集成了 rsync
命令, windows
的用户需要自行安装(教程),不然会和这位小伙伴一样遇到 command not found
,本人windows已经3年没碰了...
以上,是对上篇文章中对打包这块内容的讲解,接下来说下部署
部署 工具 我接触过walle、Jenkins
walle的话就是提交对应版本进行发布,持续集成部署方案的话就是Jenkins了。Jenkins文档
为什么要做自动化部署?结合自身实际场景描述下:
- 后端有微服务,前端自然不能落下。各个大模块(业务线)都是独立的工程,比如商城、教育、社区等等。当开发迭代一个版本时,可能就会涉及到A、B、C、D等几个项目,部署的痛苦就来了…我特么的一个个打包,然后再一个个的部署...这个过程可能半小时就过去了…效率低下又low,实力不允许这么做
- 公司有局域网限制,如果在家手动部署,还需要连接VPN,内心是拒绝的
- 我只想安心敲代码…别特么的动不动让我部署下,打断老子的思路...
当然,使用Jenkins持续集成方案,该装的环境还是一个都不能少的…这个也结合自身实际情况自行研究吧
本文也是描述下这个概念,各自实际情况各异,扔需自行研究
安装什么的自行文档吧(安装,插件,配置等),从新建任务开始
-
进入Jenkins系统,左侧新建任务
-
输入名称,选择构建一个自由风格的软件项目,确定
-
填写任务描述、源码仓库地址,分支默认master
-
配置触发器,Gitlab提交代码触发自动构建任务
-
如果需要构建时执行脚本,比如
npm i npm run build 复制代码
-
保存
很简单的几个配置步骤就能完成自动化部署任务,简单高效。自行研究尝试玩玩吧
结尾
通过这样的方式打包部署个人认为是适合绝大多数中小公司的,哈哈。我本来考虑的是将css、js部署在cdn服务器上,index.html单独部署的,考虑到暂时还没到需要这么干的程度,就不折腾服务器了,思路大同小异。
在写这篇文章的时候,正好看到 大公司里怎样开发和部署前端代码? ,大家可以了解下他们是怎么设计的。我这中小公司,感觉文中的思路方案也差不多OK的啦
提前写了,本来说是周末写的,正好今天不忙,花2小时简单写下
以上所述就是小编给大家介绍的《【前端打包部署】谈一谈我在SPA项目打包=>部署的处理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Beego打包部署到Linux
- Spring Boot打包部署和环境配置
- iOS自动化打包部署踩坑记
- 利用rpm打包上线部署golang代码的方法教程
- JFinal Undertow 2.0 发布,开发、打包、部署一体化
- 后台管理系统 icec v1.1 发布,完善打包部署脚本
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
公众号运营实战手册
中信出版社 / 2018-11 / 58
作者粥左罗在刚入行做新媒体的一年时间里,就写了100篇阅读量10万+的公众号文章,但是在此之前,他足足花了两个月的时间研究公众号运营和爆款文章的逻辑和打法。 这本书就是他总结和归纳自己公众号写作和运营的全部秘诀和技巧,是一本行之有效的实战指南。 从如何注册一个公号,给公号起什么名字? 多长时间更新一次为好? 到如何找选题,如何积累爆款素材? 如何编辑内容,如何做版面设......一起来看看 《公众号运营实战手册》 这本书的介绍吧!