如何用 TypeScript 来开发 npm 包

首先问一下自己,为什么要用 TypeScript 来开发 npm 包?

用 TypeScript 开发npm包,需要配置一堆东西,比如开发过程中需要使用ts-node或者esno这样的工具把 TS 转化为 JS后再执行,开发完成后也需要构建等等。

如果我的包比较简单,我直接用 JavaScript 不香吗?

之所以,建议使用 TypeScript 来开发 npm 包,首先最重要的一点,一定是对开发者与使用者的类型提示

无论你的包里是只有一个函数的导出,还是有零零总总大几十个函数,类型的存在都能让这个包的使用更加友好。如果你是包的使用者,你是更想"哦,这里类型报错了,我的入参类型不太对",还是"为什么这个地方一直报错呢...可恶啊,查了一通,原来是我的变量到这里的时候类型不对了"?

即使你是在 JavaScript 工程中引用 TypeScript 编写的包,只要配置了 TypeScript 开发环境,也一样能够享受到这些基于类型的辅助能力。

另外一个重要的原因则是,如果你使用了高阶的语法,此时你需要引入 Babel / Rollup 这样的编译工具来做一次语法降级,Babel 的配置略显繁琐,简单场景上 Rollup 又像高射炮打蚊子。

这个时候 TypeScript 自带的语法降级能力就香起来了:只需要简单的几行配置就够用,还带类型,还带简单的 Lint 能力...何乐而不为?

因此,本文将会从头演示如何基于 TypeScript 来编写 + 发布一个 npm 包,包括环境搭建、本地调试、编译配置以及发布等等。

本文内容分为开发阶段和打包阶段。

本地开发阶段

由于 NodeJs 不能直接执行 TS 文件,我们需要 esno 的帮助,它是一个基于 ESBuild 的执行工具,借助 ESBuild 闪电般的速度,首先编译 TS 文件然后再使用 Node 执行。

你可能会想,ESBuild 不支持类型检查吧?不用担心,VS Code 本地有类型检查,加上发布前仍然会使用 tsc 进行编译。

js 复制代码
$ npm i esno -D
$ npx esno ./src/index.ts

在日常开发时,往往会需要频繁地修改然后执行,不断查看代码的输出和表现。

在日常的网页开发中,Webpack Dev Server 已经帮我们很好地处理了这个需要,使用 JavaScript 开发 NodeJs 应用时你可能也习惯了 nodemon,那么 TypeScript 下应该怎么做?

首先,这里也是使用 nodemon,一般习惯的 nodemon index.js 只是它最基本的用法,你其实可以自由地配置文件的执行程序,以及监听哪些文件等等,在 package.json 中进行配置:

js 复制代码
{
  "nodemonConfig": {
    "delay": 500,
    "env": {
      "NODE_ENV": "development"
    },
    "execMap": {
      "ts": "esno",
      "js": "node"
    },
    "ignore": ["node_modules"],
    "verbose": true
  },
}

这样一来,在执行 nodemon index.ts 时,就能够自动使用 esno 来执行 ts 文件了。

编译配置方面,可以参考优雅的配置你的 tsconfig.json这篇文章,以模板中的配置文件为例:

js 复制代码
{
  "compilerOptions": {
    "target": "ES2018",
    "module": "ES2015",
    "types": [],
    "outDir": "dist", // 输出到 dist 目录下
    "skipLibCheck": true,
    "moduleResolution": "node",
    "strictNullChecks": true, // 开启严格检查
    "declaration": true, // 输出声明文件
    "declarationDir": "dist/type", // 声明文件放置位置
    "strict": true,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noUnusedParameters": false,
    "noUnusedLocals": false,
    "esModuleInterop": true, // ESM 与 CJS 相关,推荐开启来解决大部分问题
    "allowSyntheticDefaultImports": true, // ESM 与 CJS 相关,推荐开启来解决大部分问题
    "baseUrl": "."
  }
}

由于 npm 包需要手动指定入口,请确保 outDir 与 package.json 中的 main 指向是一致的

js 复制代码
// commonjs格式时入口文件
"main": "dist/index.umd.js",
// es格式时入口文件
"module": "dist/index.es.js",
// 声明文件入口
"types": "dist/types/index.d.ts",
// 这个参数是表面该包是es格式,这里的目的是为了引入rollup.config.js必须要加的
"type": "module"

rollup 打包

首先看一下rollup.config.js配置:

js 复制代码
import { nodeResolve } from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import typescript from 'rollup-plugin-typescript2'
import json from '@rollup/plugin-json'

export default {
  input: 'src/index.ts',
  output: [
    {
      file: './dist/index.umd.js',
      name: 'CrowllerTs',
      format: 'umd'
    },
    {
      file: './dist/index.es.js',
      format: 'es'
    }
  ],
  plugins: [
    json(),
    typescript({ useTsconfigDeclarationDir: true }),
    commonjs(),
    nodeResolve()
  ]
}
  • @rollup/plugin-node-resolve: 将编写的源码与源码依赖的第三方库进行合并,作为一个完整的包对外输出,不需要用户再去下载第三方库。
  • @rollup/plugin-commonjs:rollup 主要是用来打包es格式书写的模块,如果要打包commonjs格式书写的模块,需要使用这个插件。
  • rollup-plugin-typescript2: rollup-plugin-typescript2 插件在编译时底层也是调用typescript 把 ts 编译成 js,它也会使用tsconfig.json的配置。
  • @rollup/plugin-json: 对于json文件,比如 package.json,我们无法直接引用需要安装json插件。

最后在package.json中加上打包命令:

js 复制代码
"scripts": {
    "build": "rollup -c"
}

这里最重要的是使用rollup-plugin-typescript2来让rollup能够打包TypeScript代码。

另外,tsconfig.json中的"target": "ES5"可以帮我们将代码打包为ES5的语法,所以这里不用再使用babel来进行语法转换了。

关于 rollup 这一部分可以参考网上的资料,这里就不做详细介绍了。

相关推荐
天下无贼!1 小时前
2024年最新版TypeScript学习笔记——泛型、接口、枚举、自定义类型等知识点
前端·javascript·vue.js·笔记·学习·typescript·html
Jorah2 天前
1. TypeScript基本语法
javascript·ubuntu·typescript
小白小白从不日白3 天前
TS axios封装
前端·typescript
aimmon3 天前
Superset二次开发之源码DependencyList.tsx 分析
前端·typescript·二次开发·bi·superset
下雪天的夏风4 天前
Vant 按需引入导致 Typescript,eslint 报错问题
前端·typescript·eslint
theMuseCatcher4 天前
Vue3+TypeScript+Vite+Less 开发 H5 项目(amfe-flexible + postcss-pxtorem)
typescript·less·postcss
Qiyandays5 天前
vue + Lodop 制作可视化设计页面 实现打印设计功能(四)
前端·vue.js·typescript
人工智能的苟富贵5 天前
微信小程序中的模块化、组件化开发:完整指南
微信小程序·小程序·typescript
Code blocks7 天前
小试牛刀-区块链Solana多签账户
算法·typescript·区块链·github
shiming88797 天前
Vue 生命周期与 TypeScript:深入理解组件生命周期
前端·vue.js·typescript