generator-pipe v0.2.1
Pipe 是一套面向 H5 侵入式开发的工具,在开发者与在离线 H5 页面间建立一条代码执行通道
开发者通过编写、构建、推送任务配置文件,能够高效地对目标 H5 页面 DOM 结构、层级样式、逻辑代码 进行热变更,达到不发布业务代码实现线上变更的目的
特点
- 轻量,高效
- 对开发者透明
- 全局接入
- 执行规则、执行环境、执行时间高可配
构成
- 任务执行环境 mpi/pipe,内置于航旅前端基础库 mpi/base 中
- 任务发布入口 trip/pipe-job,面向开发者,提供任务开发、测试环境,提供任务发布、下线入口
- 构建任务 trip-tools/grunt-pipe,pipe-job 依赖,用于将各项任务构建为符合 pipe 执行规范的任务集 js 文件
- 任务脚手架 trip-tools/generator-pipe,pipe-job 依赖,为开发者提供默认任务模板
使用
Pipe 任务执行环境已集成入 base 中,开发者仅需要在 pipe-job 中配置并发布执行任务即可在线上页面执行变更
从 V3 版本开始(对应 trip/pipe-job#0.4.0 及以后版本),pipe-job 发布切换到 Aone 分支发布流程,统一进行发布审批管控
进入 Aone 应用 trip-pipe-job 新建变更,不熟悉 Aone 分支发布流程的戳这里
- 请指定正确的变更开发、测试人员,部署完成后只有测试人员有权限点击【验证通过】进入正式发布流程
将 trip/pipe-job 项目仓库 clone 到本地并安装依赖
git clone git@gitlab.alibaba-inc.com:trip/pipe-job.git
tnpm install
切换到变更分支,分支名参考 aone 变更项【分支】一栏
git checkout feature/xxxxxxxx_xxxxxxx_xxx_x
创建变更任务,完成任务基础配置,初始化配置完成后,将在 pipe-job/tasks 目录下生成对应任务目录
yo pipe
配置开发环境
启动 pipe-job 本地开发服务
grunt dev
打开任一侵入目标页面(日常/预发/线上 均可),添加 URL 参数 pipe_dev=true,如:
- 此时页面将默认请求 pipe-job 本地服务地址
完成任务开发(以任务 test_Job 为例)
HTML 任务
- index.html 内包含待插入 DOM 结构,
<!--method:prepend-->
用于指定插入方式,支持prepend(默认)
/append
/before
/after
/html
五种方式;<!--target:body-->
用于配置插入目标节点选择器,默认body
;<!--all:false-->
用于配置是否选择所有符合选择器规则的节点作为待插入节点,默认false
,仅取匹配选择器的第一个节点 - index.scss 用于添加插入 DOM 结构对应样式,默认已添加 flexible 转换方法工具
- config.js 见后文的任务配置部分
- index.html 内包含待插入 DOM 结构,
CSS 任务
- index.scss 用于添加需要注入的样式
- config.js 见后文的任务配置部分
- JS 任务
- index.js 需要注入并执行的 js 代码,代码将会在闭包中以 try...catch 方式执行
- config.js 见后文的任务配置部分
任务开发完成后,执行
预发
指令将任务推送到远程仓库grunt prepub
- 预发构建流程会执行 grunt-pipe 构建任务集
![](http://gtms02.alicdn.com/tps/i2/TB1Gqq.MXXXXXXmXpXX6RAe2pXX-750-674.png_300x300.jpg)
Aone 提交变更进入待发布状态,并勾选提交进入集成状态
- 部署完成后,打开目标页面日常/预发环境,查看效果
- 也可在任意环境添加参数 pipe_daily 强制页面拉取日常环境任务配置
任务测试通过后,执行
发布
指令将任务推送到远程仓库,此时需要选择发布类型 【灰度发布】/【正式发布】grunt publish
- publish 任务与普通 clam 项目不同点在于,这一操作并不会创建 tag 并触发 assets 发布操作,而仅是构建用于发布的静态资源并推送到远程仓库
进入 Aone trip-pipe-job 发布界面,提交发布,审批完成后,CDN 发布完成,可进行线上验证
Aone assets 发布本身没有灰度能力,因此 Pipe 的灰度发布与正式发布需在两次独立变更分别执行
任务配置
- 所有 task 下都包含一个
config.js
配置文件,用于配置任务的执行规则、执行时间、执行顺序等
配置参数:
参数名 | 类型 | 必选/默认值 | 作用 |
---|---|---|---|
name | String | 必选 | 任务名,即任务唯一标识,需符合变量名规范 |
description | String | 必选 | 任务描述,对任务功能进行简单描述 |
enable | Boolean | false | task 总控,标志当前 task 是否生效,只有生效的 task 才会被构建到执行任务集中 |
rule | String | 必选 | 匹配规则,仅匹配成功的页面执行任务,若 rule 类型为 String ,按 spm 逻辑匹配 |
Array | 必选 | 若 rule 类型为 Array ,则只要成功匹配其中一项即算通过,Array 中各项可为 String 类型或 Object 类型,按照 对应类型 逻辑处理 | |
Object | 必选 | 若 rule 类型为 Object ,可配置多个匹配属性,其中,spm /url 至少配置一个;页面在 符合所有子属性值 情况下才执行任务 | |
rule.url | String | 与 spm 至少配置一个 | 页面 Url 地址,若为 String 类型,则在 location.href 中包含字符串即通过 |
RegExp | 与 spm 至少配置一个 | 若为 RegExp 类型,则 location.href 满足正则即通过 | |
Array | 与 spm 至少配置一个 | 若为 Array 类型,则只要成功匹配其中一项即算通过,Array 中各项可为 String 类型或 RegExp 类型,按照 对应类型 逻辑处理 | |
rule.spm | String | 与 url 至少配置一个 | 页面 spm 值,若为 String 类型,则需满足 A.B 的 spm 编码格式 |
Array | 与 url 至少配置一个 | 若为 Array 类型,则只要成功匹配其中一项即算通过,Array 中各项为 String 类型 | |
rule.app | String | - | 当前所处容器,若为 String 类型,支持 LX /AP /TB /H5 ,不指定默认 全容器 |
Array | - | 若为 Array 类型,可包含多个容器 | |
rule.os | String | - | 当前所处平台,若为 String 类型,支持 ios /android /h5 ,不指定默认 全平台 |
Array | - | 若为 Array 类型,可包含多个平台 | |
rule.baseVersion | String | - | 当前基础库 base 版本号,若为 String 类型则为待匹配版本号,不指定默认 所有 base 版本 |
Array | - | 若为 Array 类型,可包含多个版本号 | |
rule.projVersion | String | - | 当前项目版本号,若为 String 类型则为待匹配版本号,不指定默认 所有项目版本 |
Array | - | 若为 Array 类型,可包含多个版本号 | |
period | Object | - | 执行时间,仅在指定时间段内执行,包含 start /end 两个子参数 |
period.start | String | - | 开始时间,若不指定默认已开始;若为 String 类型,支持传入 YYYY-MM-DD hh:mm:ss 格式字符串 |
Number | - | 若为 Number 类型,支持传入时间戳 | |
period.end | String | - | 结束时间,若不指定默认不结束;若为 String 类型,支持传入 YYYY-MM-DD hh:mm:ss 格式字符串 |
Number | - | 若为 Number 类型,支持传入时间戳 | |
runTime | Object | - | 执行时机,包含 trigger /delay 两个子参数 |
runTime.trigger | String | now | 触发执行时机,now 立即执行;ready DOMReady 后执行 |
runTime.delay | Number | 0 | 触发时机后延迟执行时间,单位 ms |
cache | Boolean | false | 是否缓存该任务 |
expireTime | Number | 0 | 任务缓存时间,单位 s |
jobs | Array | 必选 | 任务步骤及执行顺序,根据文件类型不同调用对应执行方法执行,开发者可按照 .html /.js /.css 任务文件开发规范自行添加任务执行步骤并进行顺序调整 |
Job 添加
Pipe 为复杂任务单独提供了新增 Job 的脚手架
进入需要新增 job 的 task 目录,执行命令
cd tasks/test_job
yo pipe:job
相关配置与
yo pipe
命令基本相同,task 名称无需手动输入job 添加完成后,默认将在 config.js 中添加至 jobs 最后
控制参数
- 各环境默认配置
- 开发/日常/预发 环境默认访问日常 pipe-job
- 线上 环境默认访问线上 pipe-job
- 控制访问开发环境
- 传参控制: pipe_dev=true
- 开发环境请求地址: http://localhost:8081/trip/pipe-job/pipe-job-v2.js
- 控制访问日常环境
- 传参控制: pipe_daily=true
- 日常环境请求地址: http://g-assets.daily.taobao.net/trip/pipe-job/pipe-job-v2.js
- 控制访问灰度环境
- 传参控制: pipe_gray=true
- 此处需要注意,这一操作会将灰度分桶信息写入 localStorage,后续页面访问都将走灰度,方便查看灰度效果
- 关闭 pipe(不再发送任务请求,但仍可手动调用 Pipe.run 执行任务)
- 传参关闭: disabled_pipe=true
- 添加 meta 关闭:
<meta name="disabled_pipe" content="true">
技术实现
任务构建
- 构建任务封装在 trip-tools/grunt-pipe 中,并发布到 tnpm @ali 私有域下
- JSON.parse 不支持转换 RegExp 与 function 类型对象
- 目前的解决方案是在 parse 前先转为 String 类型
- parse 完成后对正则表达式进行匹配替换,function 则传到客户端使用 eval 执行
任务脚手架
- 任务脚手架实现在 trip-tools/generator-pipe 中,并发布到 npm 下
- 提供 task/job 两个级别脚手架工具
LocalStorage 缓存
v2.0 新增特性,具体使用可参考 v2.0 升级文档
- pipe-job 最终发布到 CDN 的 js 会调用 Pipe.run 并传入一个任务列表,对于
cache: true
且expireTime > 0
的任务,Pipe 会基于 function.toString() 方法实现任务缓存到 LocalStorage 中 - LocalStorage 缓存控制相关方法从 Estelle 中复用,默认缓存时间 1 个月(localStorage 缓存时间与任务
expireTime
无关) - Pipe 初始化过程中,会优先从 LocalStorage 中读出缓存字符串并依赖
new Function
获得任务执行代码,针对每个缓存任务,若缓存时间未超过任务 config 配置的expireTime
,则立即执行,否则跳过;同时,仍然会发送 pipe-job 请求获取最新任务列表;请求返回后,对于已执行任务会跳过并更新缓存,对未执行任务会在资源加载完成后执行 - 缓存策略主要适用于对执行时机有强需求的场景:因 pipe-job 为 CDN 异步拉取,任务加载后业务代码已开始执行;若必须在业务代码前执行任务代码,则可利用缓存机制实现
- 考虑到开发者特殊需求,js 任务中可直接使用
__params
(非全局变量) 获取当前任务是否来源于缓存:var params = {};
// 为兼容老版本 Pipe,需添加 try/catch try { params = __params; } catch(e) {} // 仅缓存条件下执行 if (params && params.fromCache) { // ... } ```
- pipe-job 最终发布到 CDN 的 js 会调用 Pipe.run 并传入一个任务列表,对于
Aone 分支发布 & 发布审批 New!
v3.0 新增特性,具体使用可参考 v3.0 升级文档
- pipe-job 发布基于 Aone 分支发布模式,所有需求变更需走 Aone 标准的 变更-集成-测试-发布 流程,传统通过 publish tag 的发布方式不再支持(Aone 分支发布流程可参考这里)
- 目前 Aone 发布需走审批流程,一级审批人为一级主管,二级审批人为 Pipe 测试负责人,所有灰度、正式发布需经过两级审批后方可提交执行
灰度机制 New!
v3.0 新增特性,具体使用可参考 v3.0 升级文档
- 灰度机制:前端通过 usernick / cna 作为灰度判断因子确认用户分桶,灰度比例 10%
- 分桶判断优先级从高到低如下:
- url 添加 pipe_gray=true 传参,默认走灰度分桶,添加 localStorage 缓存,固化分桶信息
- cookie
_w_tb_nick / _nk_
获取用户昵称,计算结果添加 localStorage 缓存,固化分桶信息 - cookie
cna
,计算结果不添加 localStorage - 前端 random 判断,计算结果不添加 localStorage
- 具体实现细节可参见 trip/pipe -> src/gray-generator
注意
- 基础库新老版本兼容问题需要考虑,不同页面间适配方案兼容问题需要考虑
- 更改基础库方法注意线上代码已压缩
- base 在 head 中引入的情况需要考虑
优缺点
优点
- 多端统一发布,发布效率高
- 应对目前 TMS/EMS 支持不够友好的情况
- 避免频繁推包,减少钱包扣分
缺点
- 任务是否执行仅在进入页面时判断
- 不支持TMS配置(可以通过动态配置发送请求的方式支持)
- pipe-job 为覆盖式发布,会受封网影响