【前端打包部署】谈一谈我在SPA项目打包=>部署的处理

栏目: 编程工具 · 发布时间: 6年前

内容简介:在上篇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%(二)》 阅读

为什么这么做?

结合实际场景罗列两个吧...

  • 为了随时发布前端项目,不用等到晚上加班发布...
  • 曾经,在发布过程中,老板正在浏览…然后白屏了…所以为了发布时线上用户无感知

整体流程(画图真墨迹啊)

【前端打包部署】谈一谈我在SPA项目打包=>部署的处理
  1. 执行 run.sh ,以 beta 环境为例,项目根目录执行 ./run.sh beta

  2. run.sh 中,初始化beta环境的远程仓库,拉取代码到本地 .deploy/beta 目录,将 .deploy/beta 目录中的文件复制到本地 dist 目录

  3. run.sh 中,执行构建: npm run build_beta

  4. vue.config.js 中,创建版本号 lastVersion ,将版本号 lastVersion 加入到 cssjs 资源文件名中(我是加在最前面的,位置随意,和 task.js 中的正则对应)

  5. vue.config.js 中,注入 task.js ,执行任务

    const task = require('./task')
    task.run(lastVersion)
    复制代码
  6. task.js 中,将版本号写入 history.js ,判断是否超出最大值(最大5个历史版本),超出则执行 rmFiles() ,删除本地 dist 目录中最老的版本资源

  7. 复制本地 dist 目录文件到 .deploy/beta 中,提交 .deploy/beta 文件到远程仓库

附图:了解下.deploy/beta目录文件,history.js文件,远程Gitlab仓库代码

【前端打包部署】谈一谈我在SPA项目打包=>部署的处理
【前端打包部署】谈一谈我在SPA项目打包=>部署的处理
【前端打包部署】谈一谈我在SPA项目打包=>部署的处理

【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 ,文中用来同步本地硬盘中的不同目录。可以看下这篇教程

【前端打包部署】谈一谈我在SPA项目打包=>部署的处理

Linux 系统已经集成了 rsync 命令, windows 的用户需要自行安装(教程),不然会和这位小伙伴一样遇到 command not found ,本人windows已经3年没碰了...

以上,是对上篇文章中对打包这块内容的讲解,接下来说下部署

部署 工具 我接触过walle、Jenkins

walle的话就是提交对应版本进行发布,持续集成部署方案的话就是Jenkins了。Jenkins文档

为什么要做自动化部署?结合自身实际场景描述下:

  • 后端有微服务,前端自然不能落下。各个大模块(业务线)都是独立的工程,比如商城、教育、社区等等。当开发迭代一个版本时,可能就会涉及到A、B、C、D等几个项目,部署的痛苦就来了…我特么的一个个打包,然后再一个个的部署...这个过程可能半小时就过去了…效率低下又low,实力不允许这么做
  • 公司有局域网限制,如果在家手动部署,还需要连接VPN,内心是拒绝的
  • 我只想安心敲代码…别特么的动不动让我部署下,打断老子的思路...

当然,使用Jenkins持续集成方案,该装的环境还是一个都不能少的…这个也结合自身实际情况自行研究吧

本文也是描述下这个概念,各自实际情况各异,扔需自行研究

安装什么的自行文档吧(安装,插件,配置等),从新建任务开始

  1. 进入Jenkins系统,左侧新建任务

    【前端打包部署】谈一谈我在SPA项目打包=>部署的处理
  2. 输入名称,选择构建一个自由风格的软件项目,确定

    【前端打包部署】谈一谈我在SPA项目打包=>部署的处理
  3. 填写任务描述、源码仓库地址,分支默认master

    【前端打包部署】谈一谈我在SPA项目打包=>部署的处理
  4. 配置触发器,Gitlab提交代码触发自动构建任务

    【前端打包部署】谈一谈我在SPA项目打包=>部署的处理
  5. 如果需要构建时执行脚本,比如

    npm i
    npm run build
    复制代码
    【前端打包部署】谈一谈我在SPA项目打包=>部署的处理
  6. 保存

很简单的几个配置步骤就能完成自动化部署任务,简单高效。自行研究尝试玩玩吧

结尾

通过这样的方式打包部署个人认为是适合绝大多数中小公司的,哈哈。我本来考虑的是将css、js部署在cdn服务器上,index.html单独部署的,考虑到暂时还没到需要这么干的程度,就不折腾服务器了,思路大同小异。

在写这篇文章的时候,正好看到 大公司里怎样开发和部署前端代码? ,大家可以了解下他们是怎么设计的。我这中小公司,感觉文中的思路方案也差不多OK的啦

提前写了,本来说是周末写的,正好今天不忙,花2小时简单写下


以上所述就是小编给大家介绍的《【前端打包部署】谈一谈我在SPA项目打包=>部署的处理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Build Your Own Web Site the Right Way Using HTML & CSS

Build Your Own Web Site the Right Way Using HTML & CSS

Ian Lloyd / SitePoint / 2006-05-02 / USD 29.95

Build Your Own Website The Right Way Using HTML & CSS teaches web development from scratch, without assuming any previous knowledge of HTML, CSS or web development techniques. This book introduces you......一起来看看 《Build Your Own Web Site the Right Way Using HTML & CSS》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码