Skip to content

Commit 6b74221

Browse files
committed
refactor: bounded plugins factory instead of create hook
1 parent 1bcb67d commit 6b74221

File tree

6 files changed

+123
-76
lines changed

6 files changed

+123
-76
lines changed

docs/guide/api-vite-environment.md

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -581,22 +581,19 @@ The hook can choose to:
581581
582582
### Per-environment Plugins
583583
584-
There is a new `create` hook that plugins can define to lazily create per-environment plugins.
584+
A plugin can now also be a constructor to lazily create per-environment plugins.
585585
586586
```js
587587
function perEnvironmentPlugin() {
588-
return {
589-
name: 'per-environment-plugin',
588+
return (environment: Environment) => {
590589
// Return a plugin, an array, a Promise, or a falsy value for each environment
591-
create(environment: Environment) {
592-
if (!passesCondition(environment)) {
593-
return undefined
594-
}
595-
return [
596-
createEnvironmentPlugin(environment),
597-
otherPlugin(environment)
598-
]
590+
if (!passesCondition(environment)) {
591+
return undefined
599592
}
593+
return [
594+
createEnvironmentPlugin(environment),
595+
otherPlugin(environment)
596+
]
600597
}
601598
}
602599
```

packages/vite/src/node/build.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ import { mergeConfig } from './publicUtils'
6666
import { webWorkerPostPlugin } from './plugins/worker'
6767
import { getHookHandler } from './plugins'
6868
import { Environment } from './environment'
69-
import type { Plugin, PluginContext } from './plugin'
69+
import type { BoundedPluginConstructor, Plugin, PluginContext } from './plugin'
7070

7171
export interface BuildEnvironmentOptions {
7272
/**
@@ -534,7 +534,7 @@ export async function build(
534534
function resolveConfigToBuild(
535535
inlineConfig: InlineConfig = {},
536536
patchConfig?: (config: ResolvedConfig) => void,
537-
patchPlugins?: (plugins: Plugin[]) => void,
537+
patchPlugins?: (rawPlugins: (Plugin | BoundedPluginConstructor)[]) => void,
538538
) {
539539
return resolveConfig(
540540
inlineConfig,
@@ -1525,13 +1525,18 @@ export async function createBuilder(
15251525
lib: false,
15261526
}
15271527
}
1528-
const patchPlugins = (resolvedPlugins: Plugin[]) => {
1528+
const patchPlugins = (
1529+
rawPlugins: (Plugin | BoundedPluginConstructor)[],
1530+
) => {
15291531
// Force opt-in shared plugins
1530-
const environmentPlugins = [...resolvedPlugins]
1532+
const environmentPlugins = [...rawPlugins]
15311533
let validMixedPlugins = true
15321534
for (let i = 0; i < environmentPlugins.length; i++) {
15331535
const environmentPlugin = environmentPlugins[i]
1534-
const sharedPlugin = config.plugins[i]
1536+
if (typeof environmentPlugin === 'function') {
1537+
continue
1538+
}
1539+
const sharedPlugin = config.rawPlugins[i]
15351540
if (
15361541
config.builder.sharedPlugins ||
15371542
environmentPlugin.sharedDuringBuild
@@ -1545,7 +1550,7 @@ export async function createBuilder(
15451550
}
15461551
if (validMixedPlugins) {
15471552
for (let i = 0; i < environmentPlugins.length; i++) {
1548-
resolvedPlugins[i] = environmentPlugins[i]
1553+
rawPlugins[i] = environmentPlugins[i]
15491554
}
15501555
}
15511556
}

packages/vite/src/node/config.ts

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
FS_PREFIX,
2222
} from './constants'
2323
import type {
24+
BoundedPluginConstructor,
2425
HookHandler,
2526
Plugin,
2627
PluginEnvironment,
@@ -71,9 +72,9 @@ import {
7172
import { getFsUtils } from './fsUtils'
7273
import {
7374
createPluginHookUtils,
75+
createResolvePlugins,
7476
getHookHandler,
7577
getSortedPluginsByHook,
76-
resolvePlugins,
7778
} from './plugins'
7879
import type { ESBuildOptions } from './plugins/esbuild'
7980
import type { InternalResolveOptions, ResolveOptions } from './plugins/resolve'
@@ -538,6 +539,13 @@ export type ResolvedConfig = Readonly<
538539
alias: Alias[]
539540
}
540541
plugins: readonly Plugin[]
542+
rawPlugins: readonly (Plugin | BoundedPluginConstructor)[]
543+
/** @internal inject user plugins into the shared vite pipeline */
544+
resolvePlugins: (
545+
prePlugins: Plugin[],
546+
normalPlugins: Plugin[],
547+
postPlugins: Plugin[],
548+
) => Plugin[]
541549
css: ResolvedCSSOptions
542550
esbuild: ESBuildOptions | false
543551
server: ResolvedServerOptions
@@ -761,7 +769,9 @@ export async function resolveConfig(
761769
defaultNodeEnv = 'development',
762770
isPreview = false,
763771
patchConfig: ((config: ResolvedConfig) => void) | undefined = undefined,
764-
patchPlugins: ((plugins: Plugin[]) => void) | undefined = undefined,
772+
patchPlugins:
773+
| ((plugins: (Plugin | BoundedPluginConstructor)[]) => void)
774+
| undefined = undefined,
765775
): Promise<ResolvedConfig> {
766776
let config = inlineConfig
767777
let configFileDependencies: string[] = []
@@ -802,10 +812,10 @@ export async function resolveConfig(
802812
mode = inlineConfig.mode || config.mode || mode
803813
configEnv.mode = mode
804814

805-
const filterPlugin = (p: Plugin) => {
815+
const filterPlugin = (p: Plugin | BoundedPluginConstructor) => {
806816
if (!p) {
807817
return false
808-
} else if (!p.apply) {
818+
} else if (typeof p === 'function' || !p.apply) {
809819
return true
810820
} else if (typeof p.apply === 'function') {
811821
return p.apply({ ...config, mode }, configEnv)
@@ -815,12 +825,22 @@ export async function resolveConfig(
815825
}
816826

817827
// resolve plugins
818-
const rawUserPlugins = (
819-
(await asyncFlatten(config.plugins || [])) as Plugin[]
828+
const rawPlugins = (
829+
(await asyncFlatten(config.plugins || [])) as (
830+
| Plugin
831+
| BoundedPluginConstructor
832+
)[]
820833
).filter(filterPlugin)
821834

835+
// Backward compatibility hook used in builder, opt-in to shared plugins during build
836+
patchPlugins?.(rawPlugins)
837+
838+
const sharedPlugins = rawPlugins.filter(
839+
(plugin) => typeof plugin !== 'function',
840+
) as Plugin[]
841+
822842
const [prePlugins, normalPlugins, postPlugins] =
823-
sortUserPlugins(rawUserPlugins)
843+
sortUserPlugins(sharedPlugins)
824844

825845
const isBuild = command === 'build'
826846

@@ -1119,8 +1139,8 @@ export async function resolveConfig(
11191139
mainConfig: resolved,
11201140
bundleChain,
11211141
}
1122-
const resolvedWorkerPlugins = await resolvePlugins(
1123-
workerResolved,
1142+
const resolveWorkerPlugins = await createResolvePlugins(workerResolved)
1143+
const resolvedWorkerPlugins = resolveWorkerPlugins(
11241144
workerPrePlugins,
11251145
workerNormalPlugins,
11261146
workerPostPlugins,
@@ -1159,7 +1179,9 @@ export async function resolveConfig(
11591179
mainConfig: null,
11601180
bundleChain: [],
11611181
isProduction,
1162-
plugins: userPlugins,
1182+
plugins: userPlugins, // placeholder to be replaced
1183+
rawPlugins,
1184+
resolvePlugins: null as any, // placeholder to be replaced
11631185
css: resolveCSSOptions(config.css),
11641186
esbuild:
11651187
config.esbuild === false
@@ -1296,15 +1318,12 @@ export async function resolveConfig(
12961318
// gets called
12971319
patchConfig?.(resolved)
12981320

1299-
const resolvedPlugins = await resolvePlugins(
1300-
resolved,
1301-
prePlugins,
1302-
normalPlugins,
1303-
postPlugins,
1304-
)
1321+
const resolvePlugins = await createResolvePlugins(resolved)
1322+
1323+
;(resolved.resolvePlugins as any) = resolvePlugins
1324+
1325+
const resolvedPlugins = resolvePlugins(prePlugins, normalPlugins, postPlugins)
13051326

1306-
// Backward compatibility hook used in builder
1307-
patchPlugins?.(resolvedPlugins)
13081327
;(resolved.plugins as Plugin[]) = resolvedPlugins
13091328

13101329
Object.assign(resolved, createPluginHookUtils(resolved.plugins))

packages/vite/src/node/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,12 @@ export type {
9494
SSROptions,
9595
SSRTarget,
9696
} from './ssr'
97-
export type { Plugin, HookHandler } from './plugin'
97+
export type {
98+
BoundedPlugin,
99+
BoundedPluginConstructor,
100+
Plugin,
101+
HookHandler,
102+
} from './plugin'
98103
export type {
99104
Logger,
100105
LogOptions,

packages/vite/src/node/plugin.ts

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
ResolvedConfig,
1515
UserConfig,
1616
} from './config'
17+
import { sortUserPlugins } from './config'
1718
import type { ServerHook, ViteDevServer } from './server'
1819
import type { IndexHtmlTransform } from './plugins/html'
1920
import type { EnvironmentModuleNode } from './server/moduleGraph'
@@ -104,6 +105,20 @@ type ModifyHookContext<Hook, NewContext> = Hook extends {
104105
: ModifyFunctionContext<Hook, NewContext>
105106

106107
export interface BasePlugin<A = any> extends RollupPlugin<A> {
108+
/**
109+
* Enforce plugin invocation tier similar to webpack loaders. Hooks ordering
110+
* is still subject to the `order` property in the hook object.
111+
*
112+
* Plugin invocation order:
113+
* - alias resolution
114+
* - `enforce: 'pre'` plugins
115+
* - vite core plugins
116+
* - normal plugins
117+
* - vite build plugins
118+
* - `enforce: 'post'` plugins
119+
* - vite build post plugins
120+
*/
121+
enforce?: 'pre' | 'post'
107122
/**
108123
* Perform custom handling of HMR updates.
109124
* The handler receives a context containing changed filename, timestamp, a
@@ -203,27 +218,6 @@ export interface Plugin<A = any> extends BasePlugin<A> {
203218
* @experimental
204219
*/
205220
sharedDuringBuild?: boolean
206-
/**
207-
* Spawn the plugin into multiple plugins based on the environment.
208-
* This hook is called when the config has already been resolved, allowing to
209-
* create per environment plugin pipelines or easily inject plugins for a
210-
* only specific environments.
211-
*/
212-
create?: (environment: PluginEnvironment) => BoundedPluginOption
213-
/**
214-
* Enforce plugin invocation tier similar to webpack loaders. Hooks ordering
215-
* is still subject to the `order` property in the hook object.
216-
*
217-
* Plugin invocation order:
218-
* - alias resolution
219-
* - `enforce: 'pre'` plugins
220-
* - vite core plugins
221-
* - normal plugins
222-
* - vite build plugins
223-
* - `enforce: 'post'` plugins
224-
* - vite build post plugins
225-
*/
226-
enforce?: 'pre' | 'post'
227221
/**
228222
* Apply the plugin only for serve or build, or on certain conditions.
229223
*/
@@ -345,7 +339,12 @@ export type BoundedPluginOption =
345339
| BoundedPluginOption[]
346340
| Promise<MaybeBoundedPlugin | BoundedPluginOption[]>
347341

348-
export type MaybePlugin = Plugin | false | null | undefined
342+
export type MaybePlugin =
343+
| Plugin
344+
| BoundedPluginConstructor
345+
| false
346+
| null
347+
| undefined
349348

350349
export type PluginOption =
351350
| MaybePlugin
@@ -355,21 +354,22 @@ export type PluginOption =
355354
export async function resolveBoundedPlugins(
356355
environment: PluginEnvironment,
357356
): Promise<BoundedPlugin[]> {
358-
const resolvedPlugins: BoundedPlugin[] = []
359-
for (const plugin of environment.config.plugins) {
360-
resolvedPlugins.push(plugin)
361-
if (plugin.create) {
362-
const boundedPlugin = await plugin.create(environment)
357+
const userPlugins: BoundedPlugin[] = []
358+
for (const plugin of environment.config.rawPlugins) {
359+
if (typeof plugin === 'function') {
360+
const boundedPlugin = await plugin(environment)
363361
if (boundedPlugin) {
364362
const flatPlugins = await asyncFlattenBoundedPlugin(
365363
environment,
366364
boundedPlugin,
367365
)
368-
resolvedPlugins.push(...flatPlugins)
366+
userPlugins.push(...flatPlugins)
369367
}
368+
} else {
369+
userPlugins.push(plugin)
370370
}
371371
}
372-
return resolvedPlugins
372+
return environment.config.resolvePlugins(...sortUserPlugins(userPlugins))
373373
}
374374

375375
async function asyncFlattenBoundedPlugin(
@@ -382,7 +382,7 @@ async function asyncFlattenBoundedPlugin(
382382
do {
383383
plugins = (
384384
await Promise.all(
385-
plugins.map((p: any) => (p && p.split ? p.split(environment) : p)),
385+
plugins.map((p: any) => (typeof p === 'function' ? p(environment) : p)),
386386
)
387387
)
388388
.flat(Infinity)

0 commit comments

Comments
 (0)