使用rollup和typescript封装一个npm工具库

前一段时间正好学习了 rollup,这次为了学有所用,以使用 rollup 封装一个 npm 前端工具库来巩固所学,该前端工具库是由实验室中常见业务功能函数构成。主要包括时间处理和科学计算。

rollup 配置

rollup 是一个现代 javascript 打包工具,可以将小的代码片段合成一个大的库或者应用(redux),并且可以通过简单的配置打包多端(commonjs esmodule browser)环境。 使用 rollup 打包的库必须使用 es module 不可以使用 commonjs 或者其他模块化方式

对于一个打包工具而言,显然需要入口(input)和出口(output),为了在打包过程中插入一些特定操作,这也就有了插件(plugin)。对于不同的输出格式,常见的如 commonjs 、 es module 、浏览器格式 iife。 这三种输出只需要在 output 配置项配置 format 即可。

  1. 常用插件的使用场景
  • 如果编写的库文件中使用了第三方库(库默认是 commonjs 模块化),想将第三方库打包进源代码里,可以使用 @rollup/plugin-node-resolve 插件。
  • 如果编译打包的场景需要对编译的 js 有较高的向下兼容性要求,可以使用@rollup/plugin-babel 配置常见的预设环境 preset-env
  • 如果对编译打包的代码要压缩处理,可以使用@rollup/plugin-terser
  • 如果库文件由 typescript 编写,可以使用@rollup/plugin-typescript 作为 rollup 和 tsc 的桥梁进行打包处理,默认会读取 tsconfig.json 的配置。
  1. external 配置项:将第三方库打包到源代码里不是一个很好的选择,配置 external 后可以默认在安装该 npm 包时,会自动下载对应的 第三方包。配置就是键值对的形式,以 dayjs 为例,键是包的名字 值是 dayjs 默认导出的结果。

    1
    2
    3
    4
    5
    export default defineConfig({
    external: {
    dayjs: "dayjs",
    },
    });

    但是这种配置方式不是很合理,如果引用的第三包较多时,一个个手动配置就很麻烦了,可以直接引入 package.json 里的 dependencies 字段里的值就可以解决了,使用这种方式一定要注意,区分开发依赖和服务依赖的安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import { readFileSync } from "fs";
    const pkg = JSON.parse(readFileSync("./package.json"));
    const external = [...Object.keys(pkg.dependencies || {})].map((name) =>
    RegExp(`^${name}($|/)`)
    );

    export default defineConfig({
    input: "./index.ts",
    output: [
    {
    file: "./dist/bundle.es.mjs",
    format: "es",
    },
    {
    file: "./dist/bundle.common.js",
    format: "cjs",
    },
    ],
    external,
    });
  2. 解决 ts 打包成 js 并且 对 js 做降级兼容处理的方案,bable 和 tsc 都可以处理这个问题,这里选择了 tsc 的方案,选择使用@rollup/plugin-typescript 作 rollup 和 tsc 的桥梁,生成声明文件并且将编译打包的源代码作 es5 兼容处理。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    {
    "compilerOptions": {
    // 编译后的js代码是es5格式
    "target": "ES5",
    // 编写的ts源代码可以使用最新的ts特性
    "module": "ESNext",
    // 以node寻找文件的方式 所以可以省略扩展名.ts
    "moduleResolution": "node",
    "allowJs": true,
    // 生成.d.ts声明文件
    "declaration": true,
    // 明确声明文件生成的文件夹
    "outDir": "./dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "lib": ["ES2016", "DOM"],
    "resolveJsonModule": true
    },
    "include": ["lib/**/*", "index.ts"],
    "exclude": ["node_modules", "dist"]
    }
  3. 结合 ts 处理 压缩代码处理 完整的配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import { defineConfig } from "rollup";
    import typescript from "@rollup/plugin-typescript";
    import terser from "@rollup/plugin-terser";
    import { readFileSync } from "fs";
    const pkg = JSON.parse(readFileSync("./package.json"));
    const external = [...Object.keys(pkg.dependencies || {})].map((name) =>
    RegExp(`^${name}($|/)`)
    );
    export default defineConfig({
    input: "./index.ts",
    output: [
    {
    file: "./dist/bundle.es.mjs",
    format: "es",
    },
    {
    file: "./dist/bundle.common.js",
    format: "cjs",
    },
    ],
    external,
    plugins: [typescript(), terser()],
    });

package.json 的两个配置项

  1. main 属性: main 是 npm 包的入口文件,npm 包主要是存在于 node 环境中,所以 main 配置的文件应是 rollup 以 commonjs 格式打包的 bundle.common.js。

  2. module 属性: module 并不是 npm 官方 规定的格式,但是对于由 rollup 和 webpack 构建的环境下,这些构建工具会扫描 package.json 属性里的 module 属性,如果 module 属性里有值,那么构建环境中使用 es module 的形式引入 npm 包就会引入 module 属性配置的文件。所以 module 配置项存放的应该是 rollup 以 es 格式打包的 bundle.es.mjs。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //  d9lab_front_end_utils_pkg这个库文件
    // rollup.config.js
    export default defineConfig({
    input: "./index.ts",
    output: [
    {
    file: "./dist/bundle.es.mjs",
    format: "es",
    },
    {
    file: "./dist/bundle.common.js",
    format: "cjs",
    },
    ],
    });
    1
    2
    3
    4
    5
    6
    7
    //d9lab_front_end_utils_pkg这个库文件
    // package.json
    {
    "main": "dist/bundle.common.js",
    "module": "dist/bundle.es.js",
    "types": "dist/index.d.ts"
    }
    1
    2
    3
    // commonjs 环境使用  d9lab_front_end_utils_pkg
    // 这里d9lab_front_end_utils指向的是上述配置文件中的bundle.common.js
    const { transferTime } = require("d9lab_front_end_utils_pkg");
    1
    2
    3
    // es module使用
    //这里d9lab_front_end_utils指向的是上述配置文件中的bundle.es.js
    import { transferTime } from "d9lab_front_end_utils_pkg";

使用rollup和typescript封装一个npm工具库
https://sunburst89757.github.io/2022/12/01/rollup/
作者
Sunburst89757
发布于
2022年12月1日
许可协议