哈喽,大家好,我是 SuperYing。今天我们来聊聊如何从 0 到 1 搭建一个 Rollup + TypeScript 工具库模板工程,包括从创建文件夹开始,到依赖配置,打包编译等一整套内容。
Rollup 是一个 JavaScript 模块打包器,因此对于封装一个纯 js 库来说,无论从配置难易程度还是打包后体积来说,rollup 都是不二之选。对于 Rollup 感兴趣且不怎么熟悉的同学,可以浏览Rollup 官网了解下。
接下来我们正式开始:
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 生成,包含大多数配置项且有对应的英文注释)
方便起见,我们的项目结构规划到此为止。实际开发中,可按需添加 eslint,prettier 配置,.gitignore,.editorconfig 等。
现在我们的项目结构如下:
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 来做什么,简单点说当然是打包。但是打包后的输出文件模式有 commonjs,es module,umd 等,我们要选择哪种格式呢?小孩子才做选择,我们成年人,全都要。下面的配置比较简单的实现输出以上三种模式的文件(注释说明一切):
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 类型声明文件使用) 。
// 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
,结果如下:
编译成功,查看工程目录,发现生成了 dist 目录,commonjs,es module,umd 和 类型声明文件一应俱全。
然后在 test 目录下新建 test.js 文件(为什么用 js 文件?方便,哈哈哈),并编写如下代码:
const { sayHelloWorld } = require('../dist/index.js')
sayHelloWorld()
终端执行 npm run test
,控制台成功打印了我们想要的结果,成功!
以上就是 [从0到1搭建 Rollup + TypeScript 模板工程] 的全部内容,感谢阅读。
欢迎各路大佬讨论、批评、指正,共同进步才是硬道理!