前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 Rollup + TypeScript 编写库

使用 Rollup + TypeScript 编写库

作者头像
Innei
发布2021-12-28 10:38:06
2.3K0
发布2021-12-28 10:38:06
举报
文章被收录于专栏:静之森

本文的主题是一步一步建立 Rollup + TypeScript 代码模板。

前言

首先看看,我们需要做什么。通常一个库,在发布前他的目录树是这样的。

代码语言:javascript
复制
1.
2├── dist
3├── esm
4├── lib
5├── node_modules
6├── package.json
7├── pnpm-lock.yaml
8├── rollup.config.js
9├── src
10├── tsconfig.json
11├── vite.config.js

COPY

其中,dist 目录一般是通过 Rollup 等打包器打包后的入口文件,一般具有多种格式,以不同后缀命令,如: index.cjs.js index.esm.js。lib 和 esm 目录可以是 TypeScript 编译后生成的文件,目录下的结构基本和原项目结构相同,只是后缀变为 js,lib 一般为 CommonJS 格式,esm 为 ESModule 格式。而这些是一个库最基本的需要发布的文件。

初始化项目

通过如下命令快速开始:

bash

代码语言:javascript
复制
1npm init -y
2npm i -D typescript rollup @rollup/plugin-typescript @rollup/plugin-commonjs @rollup/plugin-node-resolve rollup-plugin-terse rollup-plugin-peer-deps-external
3npx run tsc --init
4mkdir src
5touch src/index.ts
6echo 'export {}' >> src/index.ts

COPY

注:基本配置不再过多赘述,@rollup/plugin-commonjs 为 ES6 转换插件,@rollup/plugin-node-resolve 为 Node 模块解析插件,rollup-plugin-terse 为代码压缩插件,rollup-plugin-peer-deps-external 为打包时使用外部库插件(就是说,打包的时候不把依赖库打包进去,node_modules 依赖链你也知道)。

建立 rollup.config.js,编写基本配置以支持 TypeScript。

js

代码语言:javascript
复制
1//@ts-check
2import commonjs from '@rollup/plugin-commonjs'
3import { nodeResolve } from '@rollup/plugin-node-resolve'
4import typescript from '@rollup/plugin-typescript'
5import peerDepsExternal from 'rollup-plugin-peer-deps-external'
6import { terser } from 'rollup-plugin-terser'
7
8const packageJson = require('./package.json')
9
10const umdName = packageJson.name
11
12const globals = {
13  ...packageJson.devDependencies,
14}
15
16const dir = 'dist'
17
18/**
19 * @type {import('rollup').RollupOptions[]}
20 */
21const config = [
22  {
23    input: 'src/index.ts',
24    // ignore lib
25    external: ['lodash', 'lodash-es', ...Object.keys(globals)],
26
27    output: [
28      {
29        file: dir + '/index.umd.js',
30        format: 'umd',
31        sourcemap: true,
32        name: umdName,
33      },
34      {
35        file: dir + '/index.umd.min.js',
36        format: 'umd',
37        sourcemap: true,
38        name: umdName,
39        plugins: [terser()],
40      },
41      {
42        file: dir + '/index.cjs.js',
43        format: 'cjs',
44        sourcemap: true,
45      },
46      {
47        file: dir + '/index.cjs.min.js',
48        format: 'cjs',
49        sourcemap: true,
50        plugins: [terser()],
51      },
52      {
53        file: dir + '/index.esm.js',
54        format: 'es',
55        sourcemap: true,
56      },
57      {
58        file: dir + '/index.esm.min.js',
59        format: 'es',
60        sourcemap: true,
61        plugins: [terser()],
62      },
63    ],
64    plugins: [
65      nodeResolve(),
66      commonjs({ include: 'node_modules/**' }),
67      typescript({ tsconfig: './src/tsconfig.json', declaration: false }),
68
69      // @ts-ignore
70      peerDepsExternal(),
71    ],
72
73    treeshake: true,
74  },
75]
76
77export default config

COPY

配置之后,使用 rollup -c,就可以编译打包 ts 文件到 dist 目录了。

但是这才刚刚开始。

Path Alias

一般的也会用 Path Alias 方便方法的引入。

在 tsconfig.json 配置 paths,如

json

代码语言:javascript
复制
1{
2  "compilerOptions": {
3    "baseUrl": "./src",
4    "paths": {
5      "~/*": [
6        "*"
7      ]
8    },
9  }
10}

COPY

就可以用 import foo from '~/' 的形式了。为什么要讲这个。因为这个是巨坑。请看下节。

TSC 编译与 Path Alias

上面说了 Rollup 的打包,再来说说 TSC,其实也比较简单。一般的,我会在根目录下新建一个 tsconfig.json 作为基本 tsconfig,然后在建立 build 用 tsconfig,开发用 tsconfig,都是从根目录的 extends 出来。这样做的好处就是不同环境用不同配置比较灵活。

大概这就像这样:

代码语言:javascript
复制
1.
2├── package.json
3├── pnpm-lock.yaml
4├── readme.md
5├── renovate.json
6├── rollup.config.js
7├── src
8│   ├── tsconfig.build.json # build
9│   ├── tsconfig.cjs.json # cjs build
10│   ├── tsconfig.json # dev
11├── tsconfig.json  # base
12├── vite.config.js
13└── yarn-error.log

COPY

前面说了 tsc 编译也要两种格式一个是 ESM,另一个是 CJS。就需要编写两个配置了,唯一的不同其实就是 outDirmodule。然后编译跑这行就行了。

json

代码语言:javascript
复制
1{
2  "scripts": {
3    "build": "tsc --build src/tsconfig.build.json && tsc --build src/tsconfig.cjs.json"
4  }
5}

COPY

好像没有什么不对,但是仔细一看人傻了,tsc 编译之后的产物没有把 Path Alias 转换过来。但是这个库被调包侠调过来之后,它的环境咋知道 ~ alias 是个啥,况且 js 也不读 tsconfig 的配置。

https://cdn.jsdelivr.net/gh/Innei/fancy@master/2021/1129211105.png
https://cdn.jsdelivr.net/gh/Innei/fancy@master/2021/1129211105.png

这可咋整。

一查发现别的 CLI 都用了一个工具叫 tsconfigs-paths,但是这玩意好像只是个库,用起来比较麻烦。在这之后有大佬写一个 TypeScript 的插件叫 @zerollup/ts-transform-paths。用于解决这个问题。由于目前 TypeScript 还不支持自定义 transformer 所以得用 ttypescript 替换 TypeScript。

bash

代码语言:javascript
复制
1npm i -g @zerollup/ts-transform-paths ttypescript

COPY

json

代码语言:javascript
复制
1// tsconfig.json
2{
3  "compilerOptions": {
4    "outDir": "./dist",
5    "baseUrl": "./src",
6    "paths": {
7      "~/*": [
8        "*"
9      ]
10    },
11    "plugins": [
12      {
13        "transform": "@zerollup/ts-transform-paths",
14      }
15    ]
16  }
17}

COPY

tsc 全换成 ttsc,

bash

代码语言:javascript
复制
1ttsc --build src/tsconfig.build.json && ttsc --build src/tsconfig.cjs.json"

COPY

之后。

https://cdn.jsdelivr.net/gh/Innei/fancy@master/2021/1129211825.png
https://cdn.jsdelivr.net/gh/Innei/fancy@master/2021/1129211825.png

打包 DTS

DTS 就是 tsc 生成 d.ts,我们要做的就是把 dts 也打包一份,全部扔到一个 index.d.ts。这样的话如果引用的是任何一个 dist 下的 index.js (比如dist/index.esm.js)都会识别到 type definition。

但是,@rollup/plugin-typescriptrollup-plugins-typescript2 都没有这一功能。

之后就发现了一个神器 dts-bundle-generator。可以做到这个需求,同时它也支持 Path Alias 的转换。

使用也非常的简单。

bash

代码语言:javascript
复制
1dts-bundle-generator -o build/index.d.ts src/index.ts --project tsconfig.json  --no-check

COPY

一些不能工作的点

  1. ttsc 在 typescript 4.5.2 的环境可能会报错。TypeError: Cannot read properties of undefined (reading 'impliedNodeFormat')。 解决方式:降级到 4.4.4
  2. dts-bundle-generator 不能支持没有提前引入的泛型的值的解析(也可能是 目前 TS 的 bug)参考:https://github.com/timocov/dts-bundle-generator/issues/178

Package.json

注明需要发布的文件,以及入口文件、类型文件。

json

代码语言:javascript
复制
1{
2  "main": "build/index.cjs.js",
3  "module": "build/index.esm.js",
4  "types": "build/index.d.ts",
5  "unpkg": "build/index.umd.min.js"
6}

COPY

完整模板:

rollup-typescript-lib

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 初始化项目
  • Path Alias
  • TSC 编译与 Path Alias
  • 打包 DTS
  • 一些不能工作的点
  • Package.json
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档