Skip to content

Commit 2866d4f

Browse files
committed
feat: opt-in shared plugins during build
1 parent 294a84e commit 2866d4f

File tree

2 files changed

+61
-21
lines changed

2 files changed

+61
-21
lines changed

packages/vite/src/node/build.ts

+52-21
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,8 @@ export interface ViteBuilder {
13981398
}
13991399

14001400
export interface BuilderOptions {
1401+
sharedConfigBuild?: boolean
1402+
sharedPlugins?: boolean
14011403
buildApp?: (builder: ViteBuilder) => Promise<void>
14021404
}
14031405

@@ -1411,6 +1413,8 @@ export function resolveBuilderOptions(
14111413
options: BuilderOptions = {},
14121414
): ResolvedBuilderOptions {
14131415
return {
1416+
sharedConfigBuild: options.sharedConfigBuild ?? false,
1417+
sharedPlugins: options.sharedPlugins ?? false,
14141418
buildApp: options.buildApp ?? defaultBuildApp,
14151419
}
14161420
}
@@ -1420,42 +1424,32 @@ export type ResolvedBuilderOptions = Required<BuilderOptions>
14201424
export async function createBuilder(
14211425
inlineConfig: InlineConfig = {},
14221426
): Promise<ViteBuilder> {
1423-
// Plugins passed to the Builder inline config needs to be created
1424-
// from a factory to ensure each build has their own instances
1425-
const resolveConfig = (
1426-
environmentOptions?: EnvironmentOptions,
1427-
): Promise<ResolvedConfig> => {
1428-
const environmentInlineConfig = environmentOptions
1429-
? mergeConfig(inlineConfig, environmentOptions)
1430-
: inlineConfig
1431-
1432-
// We resolve the whole config including plugins here but later on we
1433-
// need to refactor resolveConfig to only resolve the environments config
1434-
return resolveConfigToBuild(environmentInlineConfig)
1435-
}
1436-
1437-
const defaultConfig = await resolveConfig()
1427+
const config = await resolveConfigToBuild(inlineConfig)
14381428

14391429
const environments: Record<string, BuildEnvironment> = {}
14401430

14411431
const builder: ViteBuilder = {
14421432
environments,
1443-
config: defaultConfig,
1433+
config,
14441434
async buildApp() {
1445-
if (defaultConfig.build.watch) {
1435+
if (config.build.watch) {
14461436
throw new Error(
14471437
'Watch mode is not yet supported in viteBuilder.buildApp()',
14481438
)
14491439
}
1450-
return defaultConfig.builder.buildApp(builder)
1440+
return config.builder.buildApp(builder)
14511441
},
14521442
async build(environment: BuildEnvironment) {
14531443
return buildEnvironment(environment.config, environment)
14541444
},
14551445
}
14561446

1457-
for (const name of Object.keys(defaultConfig.environments)) {
1458-
const environmentOptions = defaultConfig.environments[name]
1447+
const allSharedPlugins =
1448+
config.builder.sharedPlugins ||
1449+
config.plugins.every((plugin) => plugin.sharedDuringBuild === true)
1450+
1451+
for (const name of Object.keys(config.environments)) {
1452+
const environmentOptions = config.environments[name]
14591453
const createEnvironment =
14601454
environmentOptions.build?.createEnvironment ??
14611455
((name: string, config: ResolvedConfig) =>
@@ -1466,7 +1460,44 @@ export async function createBuilder(
14661460
// expects plugins to be run for the same environment once they are created
14671461
// and to process a single bundle at a time (contrary to dev mode where
14681462
// plugins are built to handle multiple environments concurrently).
1469-
const environmentConfig = await resolveConfig(environmentOptions)
1463+
const environmentConfig =
1464+
allSharedPlugins && config.builder.sharedConfigBuild
1465+
? config
1466+
: await resolveConfigToBuild(
1467+
mergeConfig(inlineConfig, environmentOptions),
1468+
)
1469+
if (environmentConfig !== config) {
1470+
// Force opt-in shared plugins
1471+
const plugins = [...environmentConfig.plugins]
1472+
let validPlugins = true
1473+
for (let i = 0; i < plugins.length; i++) {
1474+
const environmentPlugin = plugins[i]
1475+
const sharedPlugin = config.plugins[i]
1476+
if (environmentPlugin.sharedDuringBuild) {
1477+
if (environmentPlugin.name !== sharedPlugin.name) {
1478+
validPlugins = false
1479+
break
1480+
}
1481+
plugins[i] = sharedPlugin
1482+
}
1483+
}
1484+
if (validPlugins) {
1485+
;(environmentConfig.plugins as Plugin[]) = plugins
1486+
}
1487+
}
1488+
/*
1489+
// TODO: This is implementing by merging environmentOptions into inlineConfig before resolving
1490+
// We should be instead doing the patching as the commented code below but we need to understand
1491+
// why some tests are failing first.
1492+
//
1493+
// Until the ecosystem updates to use `environment.options.build` instead of `config.build`,
1494+
// we need to make override `config.build` for the current environment.
1495+
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
1496+
// remove the default values that shouldn't be used at all once the config is resolved
1497+
if (!config.builder.sharedConfigBuild) {
1498+
;(environmentConfig.build as ResolvedBuildOptions) = { ...environmentConfig.environments[name].build, lib: false }
1499+
}
1500+
*/
14701501

14711502
const environment = await createEnvironment(name, environmentConfig)
14721503
environments[name] = environment

packages/vite/src/node/plugin.ts

+9
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@ export interface BasePlugin<A = any> extends RollupPlugin<A> {
165165
export type BoundedPlugin<A = any> = BasePlugin<A>
166166

167167
export interface Plugin<A = any> extends BasePlugin<A> {
168+
/**
169+
* Opt-in this plugin into the shared plugins pipeline.
170+
* For backward-compatibility, plugins are re-recreated for each environment
171+
* during `vite build --app`
172+
* We have an opt-in per plugin, and a general `builder.sharedPlugins`
173+
* In a future major, we'll flip the default to be shared by default
174+
* @experimental
175+
*/
176+
sharedDuringBuild?: boolean
168177
/**
169178
* Spawn the plugin into multiple plugins based on the environment.
170179
* This hook is called when the config has already been resolved, allowing to

0 commit comments

Comments
 (0)