Skip to content

Commit

Permalink
feat: support output plugins (#2916)
Browse files Browse the repository at this point in the history
<!-- Thank you for contributing! -->

### Description

<!-- Please insert your description here and provide especially info
about the "what" this PR is solving -->
  • Loading branch information
underfin authored Nov 25, 2024
1 parent dd7a173 commit 56a87a0
Show file tree
Hide file tree
Showing 12 changed files with 89 additions and 21 deletions.
15 changes: 15 additions & 0 deletions examples/basic-vue/rolldown.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,19 @@ export default defineConfig({
// aligns with Vite in the future.
conditionNames: ['import'],
},
output: {
plugins: [
{
name: 'test-plugin',
outputOptions: function (options) {
console.log(options.banner)
options.banner = '/* banner */'
return options
},
},
],
},
experimental: {
enableComposingJsPlugins: true,
},
})
18 changes: 11 additions & 7 deletions packages/rolldown/src/constants/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { Plugin } from '../plugin'

export const ENUMERATED_OUTPUT_PLUGIN_HOOK_NAMES = [
'augmentChunkHash',
'outputOptions',
'renderChunk',
'renderStart',
'renderError',
'writeBundle',
'generateBundle',
] as const

export const ENUMERATED_PLUGIN_HOOK_NAMES = [
// build hooks
'options',
Expand All @@ -8,17 +18,11 @@ export const ENUMERATED_PLUGIN_HOOK_NAMES = [
'load',
'transform',
'moduleParsed',
'augmentChunkHash',
'buildEnd',
'onLog',
'resolveDynamicImport',
// generate hooks
'generateBundle',
'outputOptions',
'renderChunk',
'renderStart',
'renderError',
'writeBundle',
...ENUMERATED_OUTPUT_PLUGIN_HOOK_NAMES,
'footer',
'banner',
'intro',
Expand Down
2 changes: 2 additions & 0 deletions packages/rolldown/src/options/output-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
SourcemapIgnoreListOption,
SourcemapPathTransformOption,
} from '../rollup'
import { RolldownOutputPluginOption } from '../plugin'

export type ModuleFormat =
| 'es'
Expand Down Expand Up @@ -72,6 +73,7 @@ export interface OutputOptions {
* - `preserve-legal`: preserve comments that contain `@license`, `@preserve` or starts with `//!` `/*!`
*/
comments?: 'none' | 'preserve-legal'
plugins?: RolldownOutputPluginOption
}

interface OverwriteOutputOptionsForCli {
Expand Down
5 changes: 5 additions & 0 deletions packages/rolldown/src/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,11 @@ export interface Plugin<A = any> extends OutputPlugin, Partial<PluginHooks> {

export type RolldownPlugin<A = any> = Plugin<A> | BuiltinPlugin | ParallelPlugin
export type RolldownPluginOption<A = any> = NullValue<RolldownPlugin<A>> | false
export type RolldownOutputPlugin = OutputPlugin | BuiltinPlugin
export type RolldownOutputPluginOption =
| NullValue<RolldownOutputPlugin>
| false
| RolldownOutputPluginOption[]
// A recursive type definition for `RolldownPlugin`, this type is used internally for `config.plugins`
export type RolldownPluginRec<A = any> =
| RolldownPluginOption<A>
Expand Down
20 changes: 16 additions & 4 deletions packages/rolldown/src/utils/create-bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,29 @@ export async function createBundler(
TreeshakingOptionsSchema.parse(inputOptions.treeshake)
}

// Convert `RolldownPluginRec` to `RolldownPlugin`
let plugins = await normalizePluginOption(inputOptions.plugins)
const inputPlugins = await normalizePluginOption(inputOptions.plugins)

const outputPlugins = await normalizePluginOption(outputOptions.plugins)

// The `outputOptions` hook is called with the input plugins and the output plugins
outputOptions = pluginDriver.callOutputOptionsHook(
[...inputPlugins, ...outputPlugins],
outputOptions,
)

let plugins = [
...inputPlugins,
// TODO give warning if `outputOptions.plugins` using build hooks
...(await normalizePluginOption(outputOptions.plugins)),
]

if (inputOptions.experimental?.enableComposingJsPlugins ?? false) {
plugins = composeJsPlugins(plugins)
}

const parallelPluginInitResult = await initializeParallelPlugins(plugins)

try {
outputOptions = pluginDriver.callOutputOptionsHook(plugins, outputOptions)

// Convert `NormalizedInputOptions` to `BindingInputOptions`
const bindingInputOptions = bindingifyInputOptions(
plugins,
Expand Down
6 changes: 3 additions & 3 deletions packages/rolldown/src/utils/normalize-plugin-option.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { asyncFlatten } from './async-flatten'
import type { RolldownPlugin } from '../plugin'
import type { RolldownPlugin, RolldownOutputPlugin } from '../plugin'
import type { InputOptions } from '../options/input-options'
import type { OutputOptions, OutputPlugin } from '../rollup-types'
import type { OutputOptions } from '../options/output-options'

export const normalizePluginOption: {
(plugins: InputOptions['plugins']): Promise<RolldownPlugin[]>
(plugins: OutputOptions['plugins']): Promise<OutputPlugin[]>
(plugins: OutputOptions['plugins']): Promise<RolldownOutputPlugin[]>
(plugins: unknown): Promise<any[]>
} = async (plugins: any) => (await asyncFlatten([plugins])).filter(Boolean)
32 changes: 32 additions & 0 deletions packages/rolldown/tests/fixtures/plugin/output-plugins/_config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { defineTest } from '@tests'
import { getOutputChunk } from '@tests/utils'
import { expect, vi } from 'vitest'

const fn = vi.fn()
const renderStartFn = vi.fn()

export default defineTest({
skipComposingJsPlugin: true, // Here mutate the test config at non-skipComposingJsPlugin test will be next skipComposingJsPlugin test failed.
config: {
output: {
plugins: [
{
name: 'test-plugin',
outputOptions: function (options) {
expect(options.banner).toBeUndefined()
options.banner = '/* banner */'
fn()
return options
},
renderStart: renderStartFn,
},
],
},
},
afterTest: (output) => {
expect(renderStartFn).toHaveBeenCalledTimes(1)
expect(fn).toHaveBeenCalledTimes(1)
const chunk = getOutputChunk(output)[0]
expect(chunk.code.includes('banner')).toBe(true)
},
})
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@

### The `input.context` is not supported
- rollup@form@custom-context: allows custom context@generates es
- rollup@function@options-in-renderstart: makes input and output options available in renderStart

### `output.dynamicImportInCjs` is not supported
- rollup@function@dynamic-import-this-function: uses correct "this" in dynamic imports when not using arrow functions
Expand Down
3 changes: 0 additions & 3 deletions packages/rollup-tests/src/ignored-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ const ignoreTests = [
"rollup@form@comment-before-import: preserves comments before imports@generates es",
"rollup@form@comment-start-inside-comment: properly remove coments above import statements@generates es",

// The output plugins hooks is not working as expected
"rollup@function@options-in-renderstart: makes input and output options available in renderStart",

// Nested plugin is not supported
"rollup@function@nested-and-async-plugin: works when nested plugin",

Expand Down
4 changes: 2 additions & 2 deletions packages/rollup-tests/src/status.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"failed": 0,
"skipFailed": 0,
"ignored": 38,
"ignored(unsupported features)": 402,
"ignored": 37,
"ignored(unsupported features)": 403,
"ignored(treeshaking)": 285,
"ignored(behavior passed, snapshot different)": 113,
"passed": 680
Expand Down
4 changes: 2 additions & 2 deletions packages/rollup-tests/src/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
|----| ---- |
| failed | 0 |
| skipFailed | 0 |
| ignored | 38 |
| ignored(unsupported features) | 402 |
| ignored | 37 |
| ignored(unsupported features) | 403 |
| ignored(treeshaking) | 285 |
| ignored(behavior passed, snapshot different) | 113 |
| passed | 680 |

0 comments on commit 56a87a0

Please sign in to comment.