背景
最近一直在采用 TDD(测试驱动开发)的方式来维护公司内部的一套通用业务逻辑
既然是应用到公司实际项目中的, 那就不能随随便便搭个脚手架来完成了
调研过程中, 发现 TypeScript library starter 和团队的技术堆栈契合的不错
因为笔者现有团队中的小伙伴项目中均采用 typescript,react(ie7 运行时切换为 qreact),redux,jest 等)进行开发(不坑队友, 选 starter 还是要符合团队的技术堆栈)
这个 Starter 还是比较完善的, 目前也一直处于迭代中
为了保证我们的代码高质量和可维护, 它使用了不少的工具(当然我们可以根据团队需要, 增删 ^_^)
至于它工具链中包含的 RollupJS,Jest,Prettier,TSLint,TypeDoc,Travis, Coveralls,Semantic release,Commitizen,Conventional changelog,Husky 等更多详细信息, 大家可以去它们的 github 或者 google 去了解
NPM Scripts
在这里, 我们把重点放在 NPM Scripts 上面, 看看这些个工具组成的开发工作流:
首先, 我们按照 README 的步骤拉取并初始化项目:
- git clone https: //github.com/alexjoverm/typescript-library-starter.git step-by-step-tdd
- cd step - by - step - tdd
npm install(通过 yarn 安装也是可以的, 淘宝源啥大家都知道哈)
NPM 包安装完成后, 会出现一个问答(主要是确认下你项目的名字, 错了可以直接在项目中改):
世界正在改变, 我们来检测并更新下包(一般情况下, 升级包不会影响原有项目):
现在, 我们来一行一行看脚本:
- lint
- npm run lint
- "lint": "tslint -t codeFrame'src/**/*.ts''test/**/*.ts'"
不用多说, 这是用来保证代码风格的, 配套项目中一般会有 tslint.json 文件(毕竟代码更多是给人看的)
-t codeFrame(就是指定 tslint 错误输出风格, 这里是 codeFrame), 官网是这么解释的:
相信大家已经秒懂了
- build & prebuild
- "prebuild": "rimraf dist"
(编译前删掉之前生成的 dist 文件夹)
npm run build(编译 ts 为各种 js 模块规范)
"build": "tsc --module commonjs --outDir dist/lib && rollup -c rollup.config.ts && typedoc --out dist/docs --target es6 --theme minimal --mode file src"
根据 tsconfig.json 采用 tsc 生成 commonjs 规范的模块
根据 tsconfig.json 采用 rollup 生成 es 规范和 umd 规范的模块
使用 typedoc 生成文档
Javscript Modules
关于 Javascript 模块的好文(有很多, 大家可以自行 google)
使用 AMDCommonJS 及 ES Harmony 编写模块化的 JavaScript
JavaScript 模块化入门: 理解模块
JavaScript 模块化入门: 模块打包构建
JavaScript Module Pattern
JavaScript 模块化编程简史
npm start
npm start(rollup 监控编译 src 目录下文件, 开发阶段使用不过我觉得开发的时候用 npm run test:watch 就够了)
- "start": "rollup -c rollup.config.ts -w"
- npm test
npm test(单元测试)
"test": "jest"
npm run test:watch(单元测试监控模式, 基本上开发时用它就够了)
jest 配置说明
针对这个 starter 所配的 jest 说明:
我们来解释下这些个选项:
"transform":node 不认识 ts, 所以需要编译后执行
"testRegex": 正则匹配要测试的文件
"moduleFileExtensions"
: 设置文件扩展名, 配置后,(import|require)相关文件不需要加啥 (.ts,.tsx,.js) 后缀
"coveragePathIgnorePatterns"
: 忽略不需要收集代码覆盖率的文件夹中的文件
"coverageThreshold"
: 这个选项用来设代码覆盖率 (code coverage) 收集的最小执行阈值
"global": 标识符, 全局设置(也可以针对路径, 单个文件来设置)
"branches": 行覆盖率(line coverage): 是否每一行都执行了?
"functions": 函数覆盖率(function coverage): 是否每个函数都调用了?
"lines": 分支覆盖率(branch coverage): 是否每个 if 代码块都执行了?
"statements": 是否每个语句都执行了?
"collectCoverage": 此项配置指示是否收集测试时的覆盖率信息
"mapCoverage": 在这里 ts 编译器产生 source map,Jest 在输出覆盖率报告时, 将尝试使用它们来映射出源代码的代码覆盖率, 并检查阈值
npm test:prod(检查代码风格, 运行单元测试并生成代码覆盖率报告)
"test:prod": "npm run lint && npm run test -- --coverage --no-cache"
实战 TDD
第一步, 我们来确定我们要解决的问题(我这里的是根据 babel 对 Preact 中 JSX 语法的转换, 来写一个简单 h 函数)
我们打开这个链接, 会看到如下代码:
大家如果看过 Preact h 函数的源码, 大家就会发现它实质上返回的是一个 VNode 实例, 它包含 4 个属性:
有了输入和输出, 我们就是撸起袖子上手干啦(gif):
根据测试用例断点调试源码
我们打开 vscode 官网所提供的项目 -->>debugging-jest-tests, 把它里面 launch.json 给拖过来(一行都不用改它的), 如下:
- {
- "version": "0.2.0",
- "configurations": [{
- "type": "node",
- "request": "launch",
- "name": "Jest All",
- "program": "${workspaceRoot}/node_modules/jest/bin/jest",
- "args": ["--runInBand"],
- "console": "integratedTerminal",
- "internalConsoleOptions": "neverOpen"
- },
- {
- "type": "node",
- "request": "launch",
- "name": "Jest Current File",
- "program": "${workspaceRoot}/node_modules/jest/bin/jest",
- "args": ["${file}"],
- "console": "integratedTerminal",
- "internalConsoleOptions": "neverOpen"
- }]
- }
注意这里的选择:
按 F5 执行断点调试的 gif:
推送到 github 并自动发布
进入 npm 官网, 注册一个账号(很简单, 就不演示了)
进入 Travis CI(持续集成, 我司用的是 gitlab CI), 点击右上角的:
可以先同步下项目, 点击:
找到你的项目(我这里是这个)
进入 coveralls(一个根据单元测试导出的数据进行分析, 展现代码覆盖率的一个工具这里, 同样是使用 github 登录)
添加仓库:
现在我们在本地运行下
npm run semantic - release - prepare
如果你是 widows 系统, 你当前可能需要运行
npm install--global--production windows - build - tools
编辑 package.json 中的 repository.url
- "author": "Kirk.Wang <kirk.w.wang@gmail.com>",
- "repository": {
- "type": "git",
- "url": "https://github.com/Kirk-Wang/step-by-step-tdd" // 这里替换成你自己的就好了
- }
根据提示, 我们运行:
- npm install - g semantic - release - cli
- semantic - release - cli setup
因为我这里创建的是一个空白项目, 并没有 git init:
首先, 我执行下
git remote add origin git@github.com: Kirk - Wang / step - by - step - tdd.git
我根据自身需要编辑下. git/config 这个件
然后检查下
gh - pages - publish.ts
(因为我们要自动发布我们的 typedoc 到 githup pages 上)
我们看下 Starter 提供的. travis.yml, 大家就清楚了, 如下:
- language: node_js
- branches:
- only:
- - master
- - /^greenkeeper/.*$/
- cache:
- yarn: true
- directories:
- - node_modules
- notifications:
- email: false
- node_js:
- - node
- script:
- - npm run test:prod && npm run build
- after_success:
- - npm run report-coverage
- - npm run deploy-docs
- - npm run semantic-release
我们接着执行:
git add .
npm run commit-->"commit": "git-cz"(因为我们要执行一个工具命令, 用来规范我们的 commit-message)
Commitizen, 一个撰写合格 Commit message 的工具
关于它正确姿势, 可以参考阮老师这篇文章:(阮老师的文章很好, 但不能全信 ^_^)
Commit message 和 Change log 编写指南
大家根据需要改一下 README.md
我们终于可以执行: git push
step-by-step-tdd typedoc 因为我这里有在 github 上绑定域名, 所以这个项目的 gh-pages 会自动在这下面
关于 gh-pages, 很简单, 看下文档就会了
Prettier & Husky & lint-staged
Prettier(统一代码风格神器)
Husky(Git Hooks 管理神器)
lint-staged(通常和 Husky 配合, 提交前使用做 Code Linting,Prettier 或者其它操作, 自由度更大)
这里推荐两篇参考文章:
我为什么推荐 Prettier 来统一代码风格
用 husky 和 lint-staged 构建超溜的代码检查工作流
来源: https://juejin.im/post/5a781c49f265da4e790fea1f