本篇文章是对 实现 Rollup 插件 alias | 使用 TypeScript 实现库的基本流程 | 使用单元测试提高开发效率 的总结。其中涉及到开发一个组件库的诸多知识点。
实现一个经常用的 alias 插件
首先执行 npm init
命令初始化一个 package.json
文件,由于插件使用了 typescript
作为类型校验,需要执行 tsc --init
命令去生成一个ts的配置文件 tsconfig.json
,执行完上述的命令之后安装项目依赖。
pnpm i rollup typescript @rollup/plugin-typescript tslib -D
先简单实现一下这个插件,插件要求导出一个方法并且返回一个对象:
// src/index.ts
import { Plugin } from 'rollup'
export function alias(): Plugin {
return {
name: 'alias',
resolveId (source: string, importer: string | undefined) {
console.log('resolveId', source, importer)
return source
}
}
}
由于 .ts
文件无法直接被运行,接下来需要将 index.ts
编译成可执行的 js
文件,新增一个配置文件rollup.config.js
,并指定输入以及输出:
// rollup.config.js
import { defineConfig } from 'rollup'
import typescript from "@rollup/plugin-typescript"
export default defineConfig({
input: './src/index.ts', // 入口文件
output: {
file: './dist/index.js', // 输出文件
format: 'es'
},
plugins: [
typescript({
module:'esnext'
})
]
})
在 package.json
里面新增一条命令,并执行pnpm build
:
"scripts": {
"build": "rollup -c rollup.config.js"
},
一般执行到这里会有一个 CommonJS
和 ES module
的类型冲突,如图所示:
我们只需要在 package.json
指定类型即可:
// package.json
{
// 省略部分代码
"type": "module",
}
再次运行 pnpm build
可以发现在 dist
目录下会生成打包完成之后的 index.js
文件。
作为一个 npm
依赖包,当别人去安装的时候需要指定执行的文件在哪,即修改 package.json
里面的 main
字段:
"main": "index.js" ——> "main": "./dist/index.js"
测试开发好的 alias 插件
在根目录下新增一个 example
文件夹并且新增测试文件 index.js、add.js
写入相关的测试代码:
// example/index.js
import { add } from './utils/add.js'
console.log(add(1, 2))
// example/utils/add.js
export function add (a, b) {
return a + b;
}
在 example
文件夹下新增配置文件 rollup.config.js
,并且补充 build
命令,由于这里使用的是 .js
为测试文件所以不需要使用 typescript
具体操作和上文类似:
// example/rollup.config.js
import { defineConfig } from 'rollup'
export default defineConfig({
input: 'index.js', // 入口文件
output: {
file: './dist/index.js', // 输出文件
format: 'es'
}
})
如何在 example
里面引入我们开发的插件呢?在 example
目录下执行如下命令就可以使用我们开发的插件。
// ../上层目录
pnpm i ../ -D
解释下上述代码的含义:
pnpm i ../ -D
是一个命令,它可以将当前项目(即插件开发项目)中的依赖包链接到上层或其他目录的项目中。
假设我们在插件开发时,需要引用某些库,这些库又已经在上层项目中安装过,在不需要重复安装依赖的情况下,可以使用 pnpm i ../ -D
命令将上层项目中的依赖包快速链接到当前开发目录中。
在执行该命令时,会寻找 ../
目录下的 package.json
文件,然后安装该文件中所包含的依赖包,并在当前项目中创建依赖的符号链接。
- …/:表示上层目录,也可以是其他目录
- -D:表示安装依赖包,并将其添加到当前项目的 devDependencies 中
这个命令一般用于本地开发、测试和调试,请注意在发布插件时,依赖的包需要在 package.json
中定义并通过 npm 或相关的包管理工具进行安装和打包。
执行完之后在会 example/package.json
新增如下代码:
"scripts": {
"build": "rollup -c rollup.config.js"
},
"devDependencies": {
"rollup": "^3.26.2",
"rollup-alias": "link:.." // 新增的依赖
}
在 example/rollup.config.js
里面引入我们编写的 alias
插件,完整的代码如下:
import { defineConfig } from 'rollup'
import { alias} from 'rollup-alias'
export default defineConfig({
input: 'index.js',
output: {
file: './dist/index.js',
format: 'es'
},
plugins: [
alias()
]
})
在此执行 pnpm build
可以发现已经成功的打印出了 log
。
为插件添加TS类型提示
首先补充插件的参数类型提示并且完善一下插件逻辑:
// rollup.config.js
import { Plugin } from 'rollup'
interface AliasOptions {
entries: { [key: string]: string }
}
export function alias(options: AliasOptions): Plugin {
const { entries } = options
return {
name: 'alias',
resolveId(source: string, importer: string | undefined) {
console.log('resolveId', source, importer)
const key = Object.keys(entries).find((e) => {
return source.startsWith(e)
})
if (!key) return source
return source.replace(key, entries[key]) + '.js'
}
}
}
执行 build
之后在我们会发现 alias
插件在传参的时候并没有对应的参数类型提示:
可以进行如下修改以完善 ts
类型提示:
- 需要在根目录下的
tsconfig.json
文件中开启"declaration": true
功能 - 同时设置
"outDir": "./dist"
- 在根目录下的
package.json
里面添加"types": "./dist/index.d.ts"
- 执行完上述操作之后再次执行
pnpm build
再次使用插件的时候就可以看到相应的提示
补充单元测试
安装 pnpm i vitest -D
,补充单元测试文件 index.spec.ts
,添加测试命令:
// src/index.spec.ts
import { describe, it, expect } from 'vitest'
import { alias } from '.'
describe('alias', () => {
it('should replace when match successful', () => {
const aliasObj:any = alias({
entries: {
'@': './utils'
}
})
expect(aliasObj.resolveId('@/add')).toBe('./utils/add.js')
})
it('should not replace when match fail', () => {
const aliasObj: any = alias({
entries: {
'@': './utils'
}
})
expect(aliasObj.resolveId('!/add')).toBe('!/add')
})
})
补充测试命令:
"scripts": {
+ "test": "vitest"
},
同时,我们需要在 build
的时候排除掉我们的测试文件在根目录下的 tsconfig.json
补充如下代码 "exclude": ["./src/*.spec.ts"]
。
然后执行pnpm test
可以看到这里的测试用例是通过的也可以证明我们写的代码是没问题的。
entries 支持数组格式
这里直接贴完成之后的代码:文章来源:https://www.toymoban.com/news/detail-576875.html
// rollup.config.js
import { Plugin } from 'rollup'
interface AliasOptions {
entries: { [key: string]: string } | { find: string, replacement: string }[]
}
export function alias(options: AliasOptions): Plugin {
const entries = normalizeEntries(options.entries)
return {
name: 'alias',
resolveId(source: string, importer: string | undefined) {
console.log('resolveId', source, importer)
const entry = entries.find((e) => e.match(source))
if (!entry) return source
return entry.replace(source)
}
}
}
function normalizeEntries(entries: AliasOptions["entries"]) {
if (Array.isArray(entries)) {
return entries.map(({ find, replacement }) => {
return new Entry(find, replacement)
})
} else {
return Object.keys(entries).map((key) => {
return new Entry(key, entries[key])
})
}
}
class Entry {
constructor(private find: string, private replacement: string) { }
match(filePath: string) {
return filePath.startsWith(this.find)
}
replace(filePath: string) {
return filePath.replace(this.find, this.replacement)
}
}
以上就简单的实现了一个 rollup
插件开发的大致流程。文章来源地址https://www.toymoban.com/news/detail-576875.html
到了这里,关于实现 Rollup 插件alias 并使用单元测试提高开发效率的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!