本系列文章将通过自己的一个开发工具库的实战经验(踩过的坑)教大家如何开发属于自己的一个工具库,在这里你可以学到 Git 的使用规范,基础项目的搭建,代码编写的规范,函数式编程思想,TypeScript 实战,单元测试,编写文档和发布 NPM 包等等知识。
阅读文章你可能需要以下基础知识:
├── master -------------------------------- 和发布版本代码保持一致
│ ├── dev -------------------------------- 开发分支
│ │ ├── feature -------------------------------- 开发新特性的分支
│ │ ├── hotfix -------------------------------- 修复 BUG 的分支
代码有编写规范,Git 提交的信息当然也要有规范啦。
<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>
type
用于说明本次提交的类型:
scope
用于说明本次改动涉及的范围,如数据层、控制层,选填。
subject
为本次提交的简要概述。
这里是一个栗子:
fix(model): fix something
- fix first bug
- fix second bug
Closes #123
可是有人不遵守或者无意识地不按格式填怎么办呢,这里就需要工具来做验证啦,我使用的是ghooks
和validate-commit-msg
,具体看下面。
想看更多 Git 提交规范知识点这里:Commit message 和 Change log 编写指南
├── .vscode ------------------------------- vscode 相关配置文件
├── dist ---------------------------------- 构建后文件的输出目录
├── docs ------------------------------ 文档
├── release ---------------------------------- Gulp 合并打包后的文件,用于 CDN 版本
├── packages ------------------------------ 存放独立发布的包的目录
├── src ----------------------------------- 源码
│ ├── __test__ -------------------------- 存放入口文件的测试用例
│ ├── <module> ------------------------------ 工具库模块
│ │ ├── __test__ ---------------------- 测试该模块的测试用例
│ │ ├── index.d.ts ---------------------- 该模块的头文件
│ │ ├── index.ts ---------------------- 该模块的实现代码
│ ├── utils.d.ts ---------------------------- 公共的头文件
│ ├── utils.ts ------------------------- 导出所有模块的文件
├── package.json
├── .eslintignore ----------------------------- eslint 忽略配置文件
├── .eslintrc.js ------------------------- eslint 配置文件
├── .gitignore --------------------------- git 忽略配置文件
├── .npmignore ------------------------------ npm 忽略配置文件,用于发布
├── .vcmrc ----------------------------- 用于检验 git 提交信息是否符合格式
├── CHANGELOG.md ------------------------- 版本更变日志
├── gulpfile.js ---------------------------- gulp
├── index.js ---------------------------- 入口文件
├── README.md ---------------------------- README
├── tsconfig.json ---------------------------- TypeScript 配置文件
{
"name": "windlike-utils", // 要发布包的名字
"version": "2.0.7", // 版本
"description": "", // 描述
"main": "index.js", // 入口文件
"scripts": {
"test": "jest", // 测试
"dev": "tsc -w --downlevelIteration", // 开发,检测代码变化并编译成 JS
"start": "node index", // 运行入口文件
"build": "tsc -d && gulp build", // 打包,编译成 JS 并用 Gulp 合并压缩
"eslint": "eslint src --ext .ts", // 检查代码格式
"eslint:fix": "eslint src --ext .ts --fix",// 检查并修复代码格式
"log": "conventional-changelog -p angular -i CHANGELOG.md -w -r 0" // 生成版本日志
},
"repository": {
"type": "git",
"url": "git+https://github.com/MrWindlike/Windlike-Utils.git"
},
"keywords": [],
"author": "Windlike",
"license": "ISC",
"bugs": {
"url": "https://github.com/MrWindlike/Windlike-Utils/issues"
},
"homepage": "https://github.com/MrWindlike/Windlike-Utils#readme",
"devDependencies": {
"@types/jest": "^23.3.0",
"awesome-typescript-loader": "^3.4.0", // TS loader
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-runtime": "^6.26.0",
"cz-conventional-changelog": "^2.1.0", // 生成版本日志的工具
"eslint": "^5.2.0",
"eslint-plugin-typescript": "^0.12.0", // eslint 检测 TS 代码的工具
"ghooks": "^2.0.4", // git 周期管理
"gulp": "^3.9.1",
"gulp-concat": "^2.6.1", // gulp 合并工具
"gulp-uglify": "^3.0.0", // gulp 压缩工具
"jest": "^23.4.1", // 测试代码的工具
"source-map-loader": "^0.2.3",
"ts-jest": "^23.0.1",
"typescript": "^2.6.2",
"typescript-eslint-parser": "^17.0.1", // eslint 检测 TS 代码的工具
"validate-commit-msg": "^2.14.0" // 验证 git 提交代码工具
},
"jest": { // jest 配置
"roots": [
"<rootDir>/src"
],
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
},
"ghooks": {
"pre-commit": "npm run eslint && npm test", // 提交前检查代码格式和运行测试用例
"commit-msg": "validate-commit-msg" // 提交时验证提交信息是否符合格式
}
}
}
使用ghooks
和validate-commit-msg
可以在 git 提交时检查信息。
"ghooks": {
"pre-commit": "npm run eslint && npm test", // 提交前检查代码格式和运行测试用例
"commit-msg": "validate-commit-msg" // 提交时验证提交信息是否符合格式
}
但还需要一个验证规则的文件.vcmrc:
{
"types": [
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"build",
"ci",
"chore",
"revert"
],
"scope": {
"required": false,
"allowed": [
"*"
],
"validate": false,
"multiple": false
},
"warnOnFail": false,
"maxSubjectLength": 100,
"subjectPattern": ".+",
"subjectPatternErrorMsg": "subject does not match subject pattern!",
"helpMessage": "",
"autoFix": false
}
这样就可以检验提交信息是否符合格式,不符合是不能提交成功的。
tsconfig.json:
{
"compilerOptions": {
"outDir": "./dist/", // 输出目录
"sourceMap": true, // 是否启用 sourceMap,用于代码调试
"noImplicitAny": true, // 是否不能含有潜在的```any```类型
"module": "commonjs", // 编译输出的模块类型
"target": "es5",
"lib": [
"es2017",
"dom"
]
},
"include": [ // 需要编译的代码
"./src/*"
]
}
这篇文章就讲到这里啦,其他的细节就不一一讲啦,想了解其他的配置文件可以到这里,下篇文章将讲下函数式编程的一些知识。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.