插件系统
robuild 基于 rolldown 的插件系统,提供了强大的扩展能力。rolldown 原生支持 JSON、CommonJS、模块解析和 React/JSX 转换,无需额外插件。
🔌 插件兼容性
Rolldown 原生支持
rolldown 内置了许多常用功能,无需额外插件:
typescript
import { defineConfig } from 'robuild'
export default defineConfig({
entries: [
{
type: 'bundle',
input: './src/index.ts',
// 以下功能原生支持,无需插件:
// - JSON 文件导入
// - CommonJS 模块
// - Node.js 模块解析
// - React/JSX 转换
// - TypeScript 编译
}
]
})Rollup 插件支持
robuild 兼容大部分 Rollup 插件:
typescript
import { defineConfig } from 'robuild'
import { visualizer } from 'rollup-plugin-visualizer'
import { terser } from 'rollup-plugin-terser'
export default defineConfig({
entries: [
{
type: 'bundle',
input: './src/index.ts',
plugins: [
// 打包分析插件
visualizer({
filename: 'dist/stats.html',
open: true
}),
// 代码压缩插件
terser({
compress: {
drop_console: true
}
})
]
}
]
})Unplugin 支持
Universal 插件支持,跨平台兼容:
typescript
import { defineConfig } from 'robuild'
import { unpluginAutoImport } from 'unplugin-auto-import/rollup'
import { unpluginIcons } from 'unplugin-icons/rollup'
export default defineConfig({
entries: [
{
type: 'bundle',
input: './src/index.ts',
plugins: [
// 自动导入插件
unpluginAutoImport({
imports: ['vue', 'vue-router'],
dts: true
}),
// 图标插件
unpluginIcons({
compiler: 'vue3'
})
]
}
]
})原生功能
1. JSON 文件支持
rolldown 原生支持 JSON 文件导入,无需额外插件:
typescript
// src/config.json
{
"name": "my-app",
"version": "1.0.0",
"features": ["auth", "dashboard"]
}
// src/index.ts
import config from './config.json'
console.log(config.name) // "my-app"
console.log(config.features) // ["auth", "dashboard"]2. React/JSX 支持
rolldown 原生支持 React 和 JSX 转换:
typescript
// src/App.tsx
import React from 'react'
export function App() {
return <div>Hello React!</div>
}
// build.config.ts
export default defineConfig({
entries: [
{
type: 'bundle',
input: './src/App.tsx',
// JSX 自动转换,无需配置
}
]
})3. CommonJS 支持
rolldown 原生支持 CommonJS 模块:
typescript
// 可以直接导入 CommonJS 模块
import lodash from 'lodash'
import express from 'express'
// 无需 @rollup/plugin-commonjs创建自定义插件
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
// version-inject-plugin.ts
import { readFileSync } from 'fs'
interface VersionInjectOptions {
packagePath?: string
placeholder?: string
}
export function versionInjectPlugin(options: VersionInjectOptions = {}) {
const { packagePath = './package.json', placeholder = '__VERSION__' } = options
return {
name: 'version-inject',
transform(code: string, id: string) {
if (code.includes(placeholder)) {
try {
const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'))
return code.replace(
new RegExp(placeholder, 'g'),
JSON.stringify(pkg.version)
)
} catch (error) {
console.warn('Failed to read package.json:', error)
}
}
return code
}
}
}2. 文件头注释插件
typescript
// banner-plugin.ts
interface BannerOptions {
banner?: string
include?: RegExp
exclude?: RegExp
}
export function bannerPlugin(options: BannerOptions = {}) {
const {
banner = '/* Generated by robuild */',
include = /\.(js|mjs|ts)$/,
exclude
} = options
return {
name: 'banner',
generateBundle(options: any, bundle: any) {
Object.keys(bundle).forEach(fileName => {
const chunk = bundle[fileName]
if (chunk.type === 'chunk') {
const shouldInclude = include.test(fileName)
const shouldExclude = exclude && exclude.test(fileName)
if (shouldInclude && !shouldExclude) {
chunk.code = `${banner}\n${chunk.code}`
}
}
})
}
}
}3. 条件编译插件
typescript
// conditional-compile-plugin.ts
interface ConditionalCompileOptions {
conditions: Record<string, boolean>
}
export function conditionalCompilePlugin(options: ConditionalCompileOptions) {
const { conditions } = options
return {
name: 'conditional-compile',
transform(code: string, id: string) {
let result = code
// 处理 #ifdef 条件编译
Object.entries(conditions).forEach(([condition, enabled]) => {
const ifdefRegex = new RegExp(
`\\/\\*\\s*#ifdef\\s+${condition}\\s*\\*\\/([\\s\\S]*?)\\/\\*\\s*#endif\\s*\\*\\/`,
'g'
)
result = result.replace(ifdefRegex, (match, content) => {
return enabled ? content.trim() : ''
})
})
return result
}
}
}插件配置最佳实践
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 { defineConfig } from 'robuild'
import { visualizer } from 'rollup-plugin-visualizer'
import { analyzer } from 'rollup-plugin-analyzer'
import { copy } from 'rollup-plugin-copy'
export default defineConfig({
entries: [
{
type: 'bundle',
input: './src/index.ts',
plugins: [
// 打包分析
visualizer({ filename: 'dist/stats.html' }),
analyzer({ summaryOnly: true }),
// 文件复制
copy({
targets: [
{ src: 'assets/*', dest: 'dist/assets' }
]
})
]
}
]
})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")