从0到1搭建 Rollup + TypeScript 模板工程

4,701 阅读6分钟

哈喽,大家好,我是 SuperYing。今天我们来聊聊如何从 0 到 1 搭建一个 Rollup + TypeScript 工具库模板工程,包括从创建文件夹开始,到依赖配置,打包编译等一整套内容。

Rollup 是一个 JavaScript 模块打包器,因此对于封装一个纯 js 库来说,无论从配置难易程度还是打包后体积来说,rollup 都是不二之选。对于 Rollup 感兴趣且不怎么熟悉的同学,可以浏览Rollup 官网了解下。

示例代码详见:github.com/ying2gege/r…

接下来我们正式开始:

1.创建 npm 工程

1.1 创建文件夹

// 切换到工作空间,创建文件夹 rollup-ts-template 
mkdir rollup-ts-template 
// 温馨提示:右键-新建文件夹更方便....

1.2 npm init

// 跳转到工程文件夹 rollup-ts-template 
cd rollup-ts-template 
// 执行 npm init 会自动生成 package.json 文件,一路回车即可 npm init

1.3 规划目录结构

接下来我们需要设计一下目录结构,目前工程下仅有一个 package.json 文件,通常情况,我们需要 src 目录放置源代码,test 目录放置测试文件。除此之外,根目录下添加以下文件:

  • README.md 文件可用来描述工具库的用途,使用方式等。
  • rollup.config.json 文件维护 rollup 配置。
  • tsconfig.json 文件维护 ts 配置(PS:建议在终端执行 tsc --init 生成,包含大多数配置项且有对应的英文注释)

方便起见,我们的项目结构规划到此为止。实际开发中,可按需添加 eslintprettier 配置,.gitignore.editorconfig 等。

现在我们的项目结构如下:

截图.png

2.依赖项配置

2.1 Rollup 相关

  • rollup
  • @rollup/plugin-node-resolve:解析第三方库依赖(即 node_module 内的依赖)
  • @rollup/plugin-commonjs:识别 commonjs 格式依赖
  • rollup-plugin-terser:(可选)代码压缩
npm i --save-dev @rollup/plugin-node-resolve @rollup/plugin-commonjs rollup rollup-plugin-terser

2.2 TypeScript 相关

  • typescript
  • rollup-plugin-typescript2:编译 TypeScript
npm i --save-dev typescript rollup-plugin-typescript2

2.3 babel 相关

  • @rollup/plugin-babel:rollup babel 插件
  • @babel/preset-env:babel 预设
  • @babel/plugin-transform-runtime:转义代码
npm i --save-dev @rollup/plugin-babel @babel/preset-env @babel/plugin-transform-runtime

3.编译配置

3.1 rollup.config.js: rolup 配置文件

首先明确下我们要使用 rollup 来做什么,简单点说当然是打包。但是打包后的输出文件模式有 commonjses moduleumd 等,我们要选择哪种格式呢?小孩子才做选择,我们成年人,全都要。下面的配置比较简单的实现输出以上三种模式的文件(注释说明一切):

import path from 'path' import resolve from '@rollup/plugin-node-resolve' 
import commonjs from '@rollup/plugin-commonjs' 
import rollupTypescript from 'rollup-plugin-typescript2' 
import babel from '@rollup/plugin-babel' 
import { DEFAULT_EXTENSIONS } from '@babel/core' 
import { terser } from 'rollup-plugin-terser' // 读取 package.json 配置 
import pkg from './package.json' // 当前运行环境,可通过 cross-env 命令行设置 
const env = process.env.NODE_ENV // umd 模式的编译结果文件输出的全局变量名称 
const name = 'RollupTsTemplate' 
const config = { 
    // 入口文件,src/index.ts 
    input: path.resolve(__dirname, 'src/index.ts'), 
    // 输出文件 
    output: [ 
        // commonjs 
        { 
            // package.json 配置的 main 属性 
            file: pkg.main, 
            format: 'cjs', 
        }, 
        // es module 
        { 
            // package.json 配置的 module 属性 
            file: pkg.module, 
            format: 'es', 
        }, 
        // umd 
        { 
            // umd 导出文件的全局变量 
            name, 
            // package.json 配置的 umd 属性 
            file: pkg.umd, 
            format: 'umd' 
        } 
    ], 
    plugins: [ 
        // 解析第三方依赖 
        resolve(), 
        // 识别 commonjs 模式第三方依赖 
        commonjs(),
        // rollup 编译 typescript 
        rollupTypescript(), 
        // babel 配置 
        babel({ 
            // 编译库使用 
            runtime babelHelpers: 'runtime', 
            // 只转换源代码,不转换外部依赖 
            exclude: 'node_modules/**', 
            // babel 默认不支持 ts 需要手动添加 
            extensions: [ 
                ...DEFAULT_EXTENSIONS, 
                '.ts', 
            ], 
        }), 
    ] 
} 
// 若打包正式环境,压缩代码 
if (env === 'production') { 
    config.plugins.push(terser({ 
        compress: { 
            pure_getters: true, 
            unsafe: true, 
            unsafe_comps: true, 
            warnings: false 
        } 
    })) 
} 

export default config

3.2 tsconfig.json 及类型编译配置 tsconfig.types.json

这里我们将 TypeScript 配置分为两个配置文件:tsconfig.json(通用配置,rollup typescript 插件使用)和 tsconfig.types.json(编译 typescript 类型声明文件使用),关于如何编译类型声明文件,可参考 rollup 编译 TypeScript 类型声明

// tsconfig.json
{ 
    "compilerOptions": 
        { 
            /* 基础选项 */ 
            "target": "esnext", /* 指定 ECMAScript 目标版本:'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 
            "module": "esnext", /* 输出的代码使用什么方式进行模块化: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 
            "lib": [ /* 指定引用的标准库 */ 
                "esnext", 
                "dom", 
                "dom.iterable", 
            ], 
            "allowJs": true,  /* 允许编译 js 文件 */ 
            "removeComments": true, /* 输出不包含注释 */ 
            /* 严格类型检查选项 */ "
            strict": true, /* 启用所有严格类型检查选项 */ 
            "noImplicitAny": true, /* 检查隐含 any 类型的表达式和声明 */
            "strictNullChecks": false, /* 严格空检查. */ 
            /* 额外检查 */ 
            "noUnusedLocals": true, /* 检查无用的变量. */ 
            /* Module Resolution Options */ 
            "moduleResolution": "node", /* 指定模块查找策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6) */ 
            "baseUrl": "./", /* 查找模块的基础目录 */ 
            "paths": { 
                "@/*": [ 
                    "src/*" 
                ] 
            }, /* 记录 baseUrl 的模块路径查找别名 */ "types": [], /* 类型声明文件 */ 
        },
    "include": [ 
        /* 指定编译处理的文件列表 */ 
        "src/*.ts", 
        "src/types.ts" 
    ], 
}
// tsconfig.types.json 
{ 
    // 继承 tsconfig.json 中的通用配置 
    "extends": "./tsconfig.json", 
    "compilerOptions": { 
        "declaration": true, /* 生成相应的 '.d.ts' file. */ 
        "declarationDir": "./dist/types", /* 类型声明文件输出目录 */
        "emitDeclarationOnly": true, /* 只生成声明文件,不生成 js 文件*/ 
        "rootDir": "./src", /* 指定输出文件目录(用于输出),用于控制输出目录结构 */ 
    } 
}

3.3 babel.config.js:babel 配置

module.exports = { 
    "presets": [ 
        [ 
            "@babel/preset-env", 
            { 
                /* Babel 会在 Rollup 有机会做处理之前,将我们的模块转成 CommonJS,导致 Rollup 的一些处理失败 */ 
                "modules": false 
            } 
        ] 
    ], 
    "plugins": [ 
        [ 
            // 与 babelHelpers: 'runtime' 配合使用 
            "@babel/plugin-transform-runtime" 
        ] 
    ] 
}

3.4 package.json

最后就是 package.json 的配置啦,我们在默认配置的基础上新增了以下配置:

  • "main": "./dist/index.js" : rollup.config.js 使用,commonjs 模式打包文件
  • "module": "./dist/index.esm.js": rollup.config.js 使用,es module 模式打包文件
  • "umd": "./dist/index.umd.js": rollup.config.js 使用,umd 模式打包文件
  • "types": "./dist/types/index.d.ts": 类型声明文件入口
  • 新增以下 npm script:
    • "clean:dist": "rimraf dist" : 清空 dist 目录。
    • "build:types": "npm run clean:dist && tsc -b ./tsconfig.types.json" : 编译 TypeScript 类型声明文件。
    • "build": "npm run build:types && rollup -c":打包,包括 TypeScript 类型声明文件和库文件。
    • "test": "node test/test.js": 执行测试文件。
    • "pretest": "npm run build":test 前置命令,执行 npm run test 前会限制性该命令。

下面是完整的 package.json:

{ 
    "name": "rollup-ts-template", 
    "version": "1.0.0", 
    "description": "", 
    "main": "./dist/index.js", 
    "module": "./dist/index.esm.js", 
    "umd": "./dist/index.umd.js", 
    "types": "./dist/types/index.d.ts",
    "scripts": { 
        "clean:dist": "rimraf dist", 
        "build:types": "npm run clean:dist && tsc -b ./tsconfig.types.json", 
        "build": "npm run build:types && rollup -c", 
        "test": "node test/test.js", 
        "pretest": "npm run build" 
    }, 
    "author": "", 
    "license": "ISC", 
    "devDependencies": { 
        "@babel/plugin-transform-runtime": "^7.17.0", 
        "@babel/preset-env": "^7.16.11", 
        "@rollup/plugin-babel": "^5.3.1", 
        "@rollup/plugin-commonjs": "^21.0.3",
        "@rollup/plugin-node-resolve": "^13.1.3", 
        "rimraf": "^3.0.2", 
        "rollup": "^2.70.1", 
        "rollup-plugin-terser": "^7.0.2", 
        "rollup-plugin-typescript2": "^0.31.2", 
        "typescript": "^4.6.3" 
    }, 
    "files": [ "dist" ] 
}

好啦,到这里我们的 Rollup + TypeScript 模板工程就搭建完成了。我们来试试效果吧。

先在 src 下新建 index.ts 文件,写点测试代码:

export function sayHelloWorld () { 
    console.log('hello world') 
}

打开终端,执行 npm run build,结果如下:

截图.png

编译成功,查看工程目录,发现生成了 dist 目录,commonjs,es module,umd 和 类型声明文件一应俱全。

截图.png

然后在 test 目录下新建 test.js 文件(为什么用 js 文件?方便,哈哈哈),并编写如下代码:

const { sayHelloWorld } = require('../dist/index.js')
sayHelloWorld()

终端执行 npm run test,控制台成功打印了我们想要的结果,成功!

截图.png

以上就是 [从0到1搭建 Rollup + TypeScript 模板工程] 的全部内容,感谢阅读。

欢迎各路大佬讨论、批评、指正,共同进步才是硬道理!