插件系统
robuild 提供了灵活的插件系统,允许你扩展和自定义构建功能。
什么是插件?
插件是扩展 robuild 功能的模块,可以:
- 转换代码: 修改源码内容
- 处理资源: 处理非 JavaScript 文件
- 添加功能: 集成外部工具和服务
- 自定义输出: 修改构建结果
插件类型
1. Rolldown 插件
用于 Bundle 模式的插件,基于 rolldown 的插件系统:
typescript
import { defineConfig } from 'robuild'
export default defineConfig({
entries: [
{
type: 'bundle',
input: './src/index.ts',
rolldown: {
plugins: [
// 使用 rolldown 插件
{
name: 'my-plugin',
setup(build) {
// 插件逻辑
}
}
]
}
}
]
})
2. Oxc 插件
用于 Transform 模式的插件,基于 oxc 的转换系统:
typescript
export default defineConfig({
entries: [
{
type: 'transform',
input: './src/runtime',
oxc: {
plugins: [
// oxc 插件配置
{
name: 'transform-plugin',
transform(code, id) {
// 转换逻辑
return code
}
}
]
}
}
]
})
内置插件
1. Shebang 插件
自动处理 shebang 行:
typescript
import { shebangPlugin } from 'robuild/plugins'
export default defineConfig({
entries: [
{
type: 'bundle',
input: './src/cli.ts',
rolldown: {
plugins: [shebangPlugin()]
}
}
]
})
功能:
- 自动添加 shebang 行到 CLI 文件
- 支持自定义 shebang 内容
- 保持可执行权限
配置选项:
typescript
shebangPlugin({
shebang: '#!/usr/bin/env node',
preserve: true
})
2. JSON 插件
处理 JSON 文件:
typescript
import { jsonPlugin } from 'robuild/plugins'
export default defineConfig({
entries: [
{
type: 'bundle',
input: './src/index.ts',
rolldown: {
plugins: [jsonPlugin()]
}
}
]
})
功能:
- 导入 JSON 文件作为模块
- 支持 JSON 路径映射
- 自动类型推断
创建自定义插件
1. 基本插件结构
typescript
// my-plugin.ts
interface MyPluginOptions {
prefix?: string
suffix?: string
}
export function myPlugin(options: MyPluginOptions = {}) {
const { prefix = '', suffix = '' } = options
return {
name: 'my-plugin',
setup(build) {
// 插件初始化逻辑
console.log('My plugin initialized')
},
transform(code, id) {
// 代码转换逻辑
if (id.endsWith('.ts') || id.endsWith('.js')) {
return `${prefix}${code}${suffix}`
}
return code
}
}
}
2. 使用自定义插件
typescript
import { defineConfig } from 'robuild'
import { myPlugin } from './my-plugin'
export default defineConfig({
entries: [
{
type: 'bundle',
input: './src/index.ts',
rolldown: {
plugins: [
myPlugin({
prefix: '// Generated by my-plugin\n',
suffix: '\n// End of generated code'
})
]
}
}
]
})
插件生命周期
1. 插件初始化
typescript
{
name: 'my-plugin',
setup(build) {
// 在构建开始时调用一次
console.log('插件初始化')
// 可以访问构建上下文
console.log('构建配置:', build.config)
}
}
2. 代码转换
typescript
{
name: 'my-plugin',
transform(code, id) {
// 对每个文件调用
if (id.endsWith('.ts')) {
// 转换 TypeScript 文件
return code.replace(/console\.log/g, '// console.log')
}
return code
}
}
3. 构建钩子
typescript
{
name: 'my-plugin',
setup(build) {
build.onStart(() => {
console.log('构建开始')
})
build.onEnd((result) => {
console.log('构建结束', result)
})
}
}
实际插件示例
1. 环境变量替换插件
typescript
// env-replace-plugin.ts
interface EnvReplaceOptions {
env?: Record<string, string>
prefix?: string
}
export function envReplacePlugin(options: EnvReplaceOptions = {}) {
const { env = process.env, prefix = 'process.env.' } = options
return {
name: 'env-replace',
transform(code, id) {
// 替换 process.env.VARIABLE 为实际值
return code.replace(
new RegExp(`${prefix}(\\w+)`, 'g'),
(match, key) => {
const value = env[key]
return value ? JSON.stringify(value) : 'undefined'
}
)
}
}
}
2. 文件大小分析插件
typescript
// size-analyzer-plugin.ts
import { readFileSync } from 'fs'
import { join } from 'path'
export function sizeAnalyzerPlugin() {
return {
name: 'size-analyzer',
setup(build) {
build.onEnd((result) => {
console.log('\n文件大小分析:')
result.outputFiles?.forEach(file => {
const stats = readFileSync(file).length
const sizeKB = (stats / 1024).toFixed(2)
console.log(` ${file}: ${sizeKB} KB`)
})
})
}
}
}
3. 自动导入插件
typescript
// auto-import-plugin.ts
interface AutoImportOptions {
imports: Record<string, string[]>
}
export function autoImportPlugin(options: AutoImportOptions) {
const { imports } = options
return {
name: 'auto-import',
transform(code, id) {
if (!id.endsWith('.ts') && !id.endsWith('.js')) {
return code
}
let importStatements = ''
// 检查代码中使用的导入
Object.entries(imports).forEach(([module, exports]) => {
const used = exports.filter(exp =>
new RegExp(`\\b${exp}\\b`).test(code)
)
if (used.length > 0) {
importStatements += `import { ${used.join(', ')} } from '${module}'\n`
}
})
return importStatements + code
}
}
}
插件配置最佳实践
1. 类型安全
typescript
// 定义插件选项类型
interface MyPluginOptions {
enabled?: boolean
config?: Record<string, any>
}
// 使用类型安全的插件
export function myPlugin(options: MyPluginOptions = {}) {
const { enabled = true, config = {} } = options
if (!enabled) {
return { name: 'my-plugin' } // 空插件
}
return {
name: 'my-plugin',
setup(build) {
// 使用配置
console.log('配置:', config)
}
}
}
2. 错误处理
typescript
export function safePlugin() {
return {
name: 'safe-plugin',
transform(code, id) {
try {
// 插件逻辑
return modifiedCode
} catch (error) {
console.error(`插件错误 (${id}):`, error)
return code // 返回原始代码
}
}
}
}
3. 性能优化
typescript
export function optimizedPlugin() {
const cache = new Map()
return {
name: 'optimized-plugin',
transform(code, id) {
// 使用缓存避免重复处理
if (cache.has(id)) {
return cache.get(id)
}
const result = processCode(code)
cache.set(id, result)
return result
}
}
}
插件生态系统
1. 官方插件
robuild 提供了一些官方插件:
typescript
import {
shebangPlugin,
jsonPlugin,
// 更多官方插件...
} from 'robuild/plugins'
2. 社区插件
社区维护的插件:
typescript
import {
vuePlugin,
reactPlugin,
// 更多社区插件...
} from '@robuild/plugins'
3. 插件开发
开发自己的插件:
bash
# 创建插件项目
mkdir robuild-plugin-example
cd robuild-plugin-example
npm init -y
# 安装开发依赖
npm install --save-dev typescript @types/node
插件调试
1. 调试模式
typescript
export default defineConfig({
entries: ['./src/index.ts'],
rolldown: {
plugins: [
{
name: 'debug-plugin',
setup(build) {
// 启用调试日志
if (process.env.DEBUG) {
console.log('插件调试信息:', build.config)
}
}
}
]
}
})
2. 插件测试
typescript
// 测试插件
import { myPlugin } from './my-plugin'
const plugin = myPlugin({ prefix: '// TEST' })
const result = plugin.transform('console.log("hello")', 'test.js')
console.log(result) // // TEST\nconsole.log("hello")