使用 TypeScript + rollup + commitizen + husky 开发JavaScript类库(1)

1,679 阅读5分钟

本文将介绍如何开发一个JavaScript类库,有兴趣的可以瞧一瞧看一看。

工欲善其事,必现利其器,IDE 推荐使用 VS Code,它有很多好用的插件。

文章主要用到以下技术栈:

  • Node.js + npm
  • TypeScript
  • rollup.js
  • commitizen
  • husky

Node.js

Node.js是一个运行在Google V8引擎上的,事件驱动的、非阻塞I/O的服务端JavaScript环境,由于前端工程师更熟悉js语法,前端代码构建打包等工具在Node.js应用非常广泛。

TypeScript

为什么选择ts,而非js作为类库的开发语言,总结以下几个原因:

  • 相比 js,ts 严谨不失灵活,编译阶段进行静态类型检查,可规避大量低级错误
  • IDE 中良好的代码提示,极大提高工作效率
  • Vue3、React 都采用 ts 进行开发,紧跟主流总是好的

虽然上手 ts 有一定的学习成本,但学好 ts 利远大于弊,特别对于多人协作的大型的项目。习惯使用 ts 后或许你再也回不去 js 了。

rollup.js

什么选择 rollup,而非 webpack 作为类库的打包工具,总结以下几个原因:

  • 相比于 webpack,rollup 设计更为小巧,打包速度更快
  • 基于ESmodules,会删除冗余代码(Tree-shaking),构建更小的包
  • React、Vue3、three.js、moment、d3 都是通过 rollup 进行打包,还是那句话,紧跟主流总是好的

当然 webpack 也非常强大,一般来说开发业务应用(包含image/css/js等多种静态资源)时使用 webpack,开发类库(只有js)时优先使用 rollup

commitizen

作为类库开发者,规范提交是必不可少的,Git 每次提交代码,都要写提交说明,如git commit -m 'xxxxxx'-m参数,就是用来指定commit message。但基本上,你写什么都行,没有规范的约束。

commitizen 是一个约束 commit message 写法规范的工具,规范有多种,本文采用使用最为广泛的 Angular 规范,规范化的 commit message,可以一目了然的知道某次 commit 的目的,也可以直接从 commit 生成 changle log。

安装 commitizen 后,凡是用到 git commit 命令,一律改为使用 git cz 命令。这时,就会出现引导提示,来生成符合规范的 commit message。

husky

上文提到凡是用到git commit命令,一律改为使用git cz命令,如果有些人不按约束提交,非要使用 git commit 命令该怎么办呢?

husky + commitlint 能很好解决是用 git commit 提交的问题。 husky 是一个Git Hooks工具,可以实现各种 Git Hook,如 pre-commit 表示 commit 前的钩子,此时可以用来做代码 lint 校验,如 commit-msg钩子,此时可以借助 commitlint 进行 commit message 格式校验,来检查是否符合你想要的提交规范。

开始动手实践吧~

安装Node.js 环境

访问网站: nodejs.org/zh-cn/, 在你的平台下载对应安装包或源码,根据指引进行安装即可。

// 查看node和npm版本号
Mac:Math fanyanbo$ node -v
v14.15.0
Mac:Math fanyanbo$ npm -v
6.14.8

如果你想在电脑上安装多个 Node.js 版本,可参考这篇文章:Node.js 多版本切换实践

创建项目

创建 Math 目录,执行npm init, 填写version、description、keywords、author等信息,生成 package.json

Mac:juejin fanyanbo$ mkdir Math
Mac:juejin fanyanbo$ touch Math/README.md
Mac:juejin fanyanbo$ cd Math
Mac:Math fanyanbo$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (math) 
version: (1.0.0description: a math library for javascript
entry point: (index.js) 
test command: 
git repository: 
keywords: math
author: kuiper
license: (ISC) MIT
About to write to /Users/fanyanbo/juejin/Math/package.json:

{
  "name""math",
  "version""1.0.0",
  "description""a math library for javascript",
  "main""index.js",
  "scripts": {
    "test""echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "math"
  ],
  "author""kuiper",
  "license""MIT"
}


Is this OK? (yes) 

编写代码

本地安装 typescript, 建议使用 npm 淘宝镜像,安装会快很多

Mac:Math fanyanbo$ npm i -D typescript --registry https://registry.npm.taobao.org
npm WARN @rollup/pluginutils@3.1.0 requires a peer of rollup@^1.20.0||^2.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN rollup-plugin-node-resolve@5.2.0 requires a peer of rollup@>=1.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN rollup-plugin-typescript2@0.29.0 requires a peer of rollup@>=1.26.3 but none is installed. You must install peer dependencies yourself.
npm WARN math@1.0.0 No repository field.

+ typescript@4.1.3
added 1 package from 1 contributor in 0.925s

5 packages are looking for funding
  run `npm fund` for details

根目录下创建 src 目录和代码文件 index.ts

Mac:Math fanyanbomkdir src
Mac:Math fanyanbotouch src/index.ts

Math 类库提供两个数字的加减乘除功能,库内容不是本文重点,仅提供简单示例,代码如下,

//src/index.ts
function add(x: number, y: number): number {
    return x + y
}

function sub(x: number, y: number): number {
    return x - y
}

function multi(x: number, y: number): number {
    return x * y
}

function div(x: number, y: number): number {
    if (y === 0throw new Error("The divisor cannot be 0")
    return x / y
}

export {
    add, sub, multi, div
}

想进一步学习 TypeScript,请戳这里

构建打包

  1. 全局安装 rollup,当然本地安装也可以,我经常使用 rollup 打包工具,所以选择了全局安装。
// Mac上全局安装加上sudo,否则报access错误
Mac:Math fanyanbo$ npm install -g rollup
Mac:Math fanyanbo$ rollup -v
rollup v1.24.0
  1. 本地安装 rollup 相关插件
Mac:Math fanyanbo$ npm i -D rollup-plugin-typescript2 --registry  https://registry.npm.taobao.org
npm WARN rollup-plugin-node-resolve@5.2.0 requires a peer of rollup@>=1.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN rollup-plugin-typescript2@0.29.0 requires a peer of rollup@>=1.26.3 but none is installed. You must install peer dependencies yourself.
npm WARN rollup-plugin-typescript2@0.29.0 requires a peer of typescript@>=2.4.0 but none is installed. You must install peer dependencies yourself.
npm WARN @rollup/pluginutils@3.1.0 requires a peer of rollup@^1.20.0||^2.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN math@1.0.0 No repository field.

+ rollup-plugin-typescript2@0.29.0
updated 1 package in 2.087s

1 package is looking for funding
  run `npm fund` for details

rollup 中将 TypeScript 转换成 JavaScript 需要 rollup-plugin-typescript2 插件

  1. 配置rollup.config.js
// 根目录创建配置文件
Mac:Math fanyanbo$ touch rollup.config.js
// rollup.config.js
import typescript2 from 'rollup-plugin-typescript2'

export default {
    input'./src/index.ts',
    output: [
        {
            file`dist/math-es.js`,
            format'es'
        },
        {
            file`dist/math-cjs.js`,
            format'cjs'
        }
    ],
    plugins: [
        typescript2()
    ]
}

如上所示,打包的入口文件是 src/index.ts,分别以 es 标准和 commonjs 标准输出打包后的文件到 dist 目录下

  1. 生成库文件
Mac:Math fanyanbo$ rollup -c

./src/index.ts → dist/math-es.js, dist/math-cjs.js...
created dist/math-es.js, dist/math-cjs.js in 614ms

也可以在 package.json 的 scripts 中配置"build": "rollup -c",再执行 npm run build,也是一样的效果,最终 ts 转成了 js

  1. 使用打包好的库文件
// 创建test文件
Mac:Math fanyanbo$ mkdir test
Mac:Math fanyanbo$ touch test/index.js
// test/index.js
const math = require('../dist/math-cjs')

console.log(math.add(12))
console.log(math.sub(12))
console.log(math.multi(12))
console.log(math.div(12))
[Running] node "/Users/fanyanbo/juejin/Math/test/index.js"
3
-1
2
0.5

想进一步学习 rollup 打包,请戳这里

由于篇幅字数限制,后续内容请戳这里:
使用 TypeScript + rollup + commitizen + husky 开发JavaScript类库 (2)