Skip to content

Commit cc61d16

Browse files
authored
refactor: use builder in build (#18432)
1 parent 19ce525 commit cc61d16

File tree

5 files changed

+83
-124
lines changed

5 files changed

+83
-124
lines changed

docs/guide/api-environment-frameworks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ export function createHandler(input) {
266266

267267
In the CLI, calling `vite build` and `vite build --ssr` will still build the client only and ssr only environments for backward compatibility.
268268

269-
When `builder.entireApp` is `true` (or when calling `vite build --app`), `vite build` will opt-in into building the entire app instead. This would later on become the default in a future major. A `ViteBuilder` instance will be created (build-time equivalent to a `ViteDevServer`) to build all configured environments for production. By default the build of environments is run in series respecting the order of the `environments` record. A framework or user can further configure how the environments are built using:
269+
When `builder` is not `undefined` (or when calling `vite build --app`), `vite build` will opt-in into building the entire app instead. This would later on become the default in a future major. A `ViteBuilder` instance will be created (build-time equivalent to a `ViteDevServer`) to build all configured environments for production. By default the build of environments is run in series respecting the order of the `environments` record. A framework or user can further configure how the environments are built using:
270270

271271
```js
272272
export default {

docs/guide/cli.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ vite build [root]
6969
| `-f, --filter <filter>` | Filter debug logs (`string`) |
7070
| `-m, --mode <mode>` | Set env mode (`string`) |
7171
| `-h, --help` | Display available CLI options |
72-
| `--app` | Build all environments, same as `builder.entireApp` (`boolean`, experimental) |
72+
| `--app` | Build all environments, same as `builder: {}` (`boolean`, experimental) |
7373

7474
## Others
7575

packages/vite/src/node/build.ts

Lines changed: 73 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -493,35 +493,13 @@ export async function resolveBuildPlugins(config: ResolvedConfig): Promise<{
493493
export async function build(
494494
inlineConfig: InlineConfig = {},
495495
): Promise<RollupOutput | RollupOutput[] | RollupWatcher> {
496-
const patchConfig = (resolved: ResolvedConfig) => {
497-
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
498-
// we need to make override `config.build` for the current environment.
499-
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
500-
// remove the default values that shouldn't be used at all once the config is resolved
501-
const environmentName = resolved.build.ssr ? 'ssr' : 'client'
502-
;(resolved.build as ResolvedBuildOptions) = {
503-
...resolved.environments[environmentName].build,
504-
}
505-
}
506-
const config = await resolveConfigToBuild(inlineConfig, patchConfig)
507-
return buildWithResolvedConfig(config)
496+
const builder = await createBuilder(inlineConfig, true)
497+
const environment = Object.values(builder.environments)[0]
498+
if (!environment) throw new Error('No environment found')
499+
return builder.build(environment)
508500
}
509501

510-
/**
511-
* @internal used to implement `vite build` for backward compatibility
512-
*/
513-
export async function buildWithResolvedConfig(
514-
config: ResolvedConfig,
515-
): Promise<RollupOutput | RollupOutput[] | RollupWatcher> {
516-
const environmentName = config.build.ssr ? 'ssr' : 'client'
517-
const environment = await config.environments[
518-
environmentName
519-
].build.createEnvironment(environmentName, config)
520-
await environment.init()
521-
return buildEnvironment(environment)
522-
}
523-
524-
export function resolveConfigToBuild(
502+
function resolveConfigToBuild(
525503
inlineConfig: InlineConfig = {},
526504
patchConfig?: (config: ResolvedConfig) => void,
527505
patchPlugins?: (resolvedPlugins: Plugin[]) => void,
@@ -540,7 +518,7 @@ export function resolveConfigToBuild(
540518
/**
541519
* Build an App environment, or a App library (if libraryOptions is provided)
542520
**/
543-
export async function buildEnvironment(
521+
async function buildEnvironment(
544522
environment: BuildEnvironment,
545523
): Promise<RollupOutput | RollupOutput[] | RollupWatcher> {
546524
const { root, packageCache } = environment.config
@@ -1486,7 +1464,6 @@ export interface ViteBuilder {
14861464
export interface BuilderOptions {
14871465
sharedConfigBuild?: boolean
14881466
sharedPlugins?: boolean
1489-
entireApp?: boolean
14901467
buildApp?: (builder: ViteBuilder) => Promise<void>
14911468
}
14921469

@@ -1497,12 +1474,12 @@ async function defaultBuildApp(builder: ViteBuilder): Promise<void> {
14971474
}
14981475

14991476
export function resolveBuilderOptions(
1500-
options: BuilderOptions = {},
1501-
): ResolvedBuilderOptions {
1477+
options: BuilderOptions | undefined,
1478+
): ResolvedBuilderOptions | undefined {
1479+
if (!options) return
15021480
return {
15031481
sharedConfigBuild: options.sharedConfigBuild ?? false,
15041482
sharedPlugins: options.sharedPlugins ?? false,
1505-
entireApp: options.entireApp ?? false,
15061483
buildApp: options.buildApp ?? defaultBuildApp,
15071484
}
15081485
}
@@ -1515,83 +1492,91 @@ export type ResolvedBuilderOptions = Required<BuilderOptions>
15151492
*/
15161493
export async function createBuilder(
15171494
inlineConfig: InlineConfig = {},
1495+
useLegacyBuilder: null | boolean = false,
15181496
): Promise<ViteBuilder> {
1519-
const config = await resolveConfigToBuild(inlineConfig)
1520-
return createBuilderWithResolvedConfig(inlineConfig, config)
1521-
}
1497+
const patchConfig = (resolved: ResolvedConfig) => {
1498+
if (!(useLegacyBuilder ?? !resolved.builder)) return
1499+
1500+
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
1501+
// we need to make override `config.build` for the current environment.
1502+
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
1503+
// remove the default values that shouldn't be used at all once the config is resolved
1504+
const environmentName = resolved.build.ssr ? 'ssr' : 'client'
1505+
;(resolved.build as ResolvedBuildOptions) = {
1506+
...resolved.environments[environmentName].build,
1507+
}
1508+
}
1509+
const config = await resolveConfigToBuild(inlineConfig, patchConfig)
1510+
useLegacyBuilder ??= !config.builder
1511+
const configBuilder = config.builder ?? resolveBuilderOptions({})!
15221512

1523-
/**
1524-
* Used to implement the `vite build` command without resolving the config twice
1525-
* @internal
1526-
*/
1527-
export async function createBuilderWithResolvedConfig(
1528-
inlineConfig: InlineConfig,
1529-
config: ResolvedConfig,
1530-
): Promise<ViteBuilder> {
15311513
const environments: Record<string, BuildEnvironment> = {}
15321514

15331515
const builder: ViteBuilder = {
15341516
environments,
15351517
config,
15361518
async buildApp() {
1537-
return config.builder.buildApp(builder)
1519+
return configBuilder.buildApp(builder)
15381520
},
15391521
async build(environment: BuildEnvironment) {
15401522
return buildEnvironment(environment)
15411523
},
15421524
}
15431525

1544-
for (const environmentName of Object.keys(config.environments)) {
1545-
// We need to resolve the config again so we can properly merge options
1546-
// and get a new set of plugins for each build environment. The ecosystem
1547-
// expects plugins to be run for the same environment once they are created
1548-
// and to process a single bundle at a time (contrary to dev mode where
1549-
// plugins are built to handle multiple environments concurrently).
1550-
let environmentConfig = config
1551-
if (!config.builder.sharedConfigBuild) {
1552-
const patchConfig = (resolved: ResolvedConfig) => {
1553-
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
1554-
// we need to make override `config.build` for the current environment.
1555-
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
1556-
// remove the default values that shouldn't be used at all once the config is resolved
1557-
;(resolved.build as ResolvedBuildOptions) = {
1558-
...resolved.environments[environmentName].build,
1526+
async function setupEnvironment(name: string, config: ResolvedConfig) {
1527+
const environment = await config.build.createEnvironment(name, config)
1528+
await environment.init()
1529+
environments[name] = environment
1530+
}
1531+
1532+
if (useLegacyBuilder) {
1533+
await setupEnvironment(config.build.ssr ? 'ssr' : 'client', config)
1534+
} else {
1535+
for (const environmentName of Object.keys(config.environments)) {
1536+
// We need to resolve the config again so we can properly merge options
1537+
// and get a new set of plugins for each build environment. The ecosystem
1538+
// expects plugins to be run for the same environment once they are created
1539+
// and to process a single bundle at a time (contrary to dev mode where
1540+
// plugins are built to handle multiple environments concurrently).
1541+
let environmentConfig = config
1542+
if (!configBuilder.sharedConfigBuild) {
1543+
const patchConfig = (resolved: ResolvedConfig) => {
1544+
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
1545+
// we need to make override `config.build` for the current environment.
1546+
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
1547+
// remove the default values that shouldn't be used at all once the config is resolved
1548+
;(resolved.build as ResolvedBuildOptions) = {
1549+
...resolved.environments[environmentName].build,
1550+
}
15591551
}
1560-
}
1561-
const patchPlugins = (resolvedPlugins: Plugin[]) => {
1562-
// Force opt-in shared plugins
1563-
let j = 0
1564-
for (let i = 0; i < resolvedPlugins.length; i++) {
1565-
const environmentPlugin = resolvedPlugins[i]
1566-
if (
1567-
config.builder.sharedPlugins ||
1568-
environmentPlugin.sharedDuringBuild
1569-
) {
1570-
for (let k = j; k < config.plugins.length; k++) {
1571-
if (environmentPlugin.name === config.plugins[k].name) {
1572-
resolvedPlugins[i] = config.plugins[k]
1573-
j = k + 1
1574-
break
1552+
const patchPlugins = (resolvedPlugins: Plugin[]) => {
1553+
// Force opt-in shared plugins
1554+
let j = 0
1555+
for (let i = 0; i < resolvedPlugins.length; i++) {
1556+
const environmentPlugin = resolvedPlugins[i]
1557+
if (
1558+
configBuilder.sharedPlugins ||
1559+
environmentPlugin.sharedDuringBuild
1560+
) {
1561+
for (let k = j; k < config.plugins.length; k++) {
1562+
if (environmentPlugin.name === config.plugins[k].name) {
1563+
resolvedPlugins[i] = config.plugins[k]
1564+
j = k + 1
1565+
break
1566+
}
15751567
}
15761568
}
15771569
}
15781570
}
1571+
environmentConfig = await resolveConfigToBuild(
1572+
inlineConfig,
1573+
patchConfig,
1574+
patchPlugins,
1575+
)
15791576
}
1580-
environmentConfig = await resolveConfigToBuild(
1581-
inlineConfig,
1582-
patchConfig,
1583-
patchPlugins,
1584-
)
1585-
}
1586-
1587-
const environment = await environmentConfig.build.createEnvironment(
1588-
environmentName,
1589-
environmentConfig,
1590-
)
15911577

1592-
await environment.init()
1593-
1594-
environments[environmentName] = environment
1578+
await setupEnvironment(environmentName, environmentConfig)
1579+
}
15951580
}
15961581

15971582
return builder

packages/vite/src/node/cli.ts

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import { performance } from 'node:perf_hooks'
44
import { cac } from 'cac'
55
import colors from 'picocolors'
66
import { VERSION } from './constants'
7-
import type { BuildEnvironmentOptions, ResolvedBuildOptions } from './build'
7+
import type { BuildEnvironmentOptions } from './build'
88
import type { ServerOptions } from './server'
99
import type { CLIShortcut } from './shortcuts'
1010
import type { LogLevel } from './logger'
1111
import { createLogger } from './logger'
1212
import { resolveConfig } from './config'
13-
import type { InlineConfig, ResolvedConfig } from './config'
13+
import type { InlineConfig } from './config'
1414

1515
const cli = cac('vite')
1616

@@ -285,14 +285,14 @@ cli
285285
`[boolean] force empty outDir when it's outside of root`,
286286
)
287287
.option('-w, --watch', `[boolean] rebuilds when modules have changed on disk`)
288-
.option('--app', `[boolean] same as builder.entireApp`)
288+
.option('--app', `[boolean] same as \`builder: {}\``)
289289
.action(
290290
async (
291291
root: string,
292292
options: BuildEnvironmentOptions & BuilderCLIOptions & GlobalCLIOptions,
293293
) => {
294294
filterDuplicateOptions(options)
295-
const build = await import('./build')
295+
const { createBuilder } = await import('./build')
296296

297297
const buildOptions: BuildEnvironmentOptions = cleanGlobalCLIOptions(
298298
cleanBuilderCLIOptions(options),
@@ -307,36 +307,10 @@ cli
307307
logLevel: options.logLevel,
308308
clearScreen: options.clearScreen,
309309
build: buildOptions,
310-
...(options.app ? { builder: { entireApp: true } } : {}),
311-
}
312-
const patchConfig = (resolved: ResolvedConfig) => {
313-
if (resolved.builder.entireApp) {
314-
return
315-
}
316-
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
317-
// we need to make override `config.build` for the current environment.
318-
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
319-
// remove the default values that shouldn't be used at all once the config is resolved
320-
const environmentName = resolved.build.ssr ? 'ssr' : 'client'
321-
;(resolved.build as ResolvedBuildOptions) = {
322-
...resolved.environments[environmentName].build,
323-
}
324-
}
325-
const config = await build.resolveConfigToBuild(
326-
inlineConfig,
327-
patchConfig,
328-
)
329-
330-
if (config.builder.entireApp) {
331-
const builder = await build.createBuilderWithResolvedConfig(
332-
inlineConfig,
333-
config,
334-
)
335-
await builder.buildApp()
336-
} else {
337-
// Single environment (client or ssr) build or library mode build
338-
await build.buildWithResolvedConfig(config)
310+
...(options.app ? { builder: {} } : {}),
339311
}
312+
const builder = await createBuilder(inlineConfig, null)
313+
await builder.buildApp()
340314
} catch (e) {
341315
createLogger(options.logLevel).error(
342316
colors.red(`error during build:\n${e.stack}`),

packages/vite/src/node/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ export type ResolvedConfig = Readonly<
566566
server: ResolvedServerOptions
567567
dev: ResolvedDevEnvironmentOptions
568568
/** @experimental */
569-
builder: ResolvedBuilderOptions
569+
builder: ResolvedBuilderOptions | undefined
570570
build: ResolvedBuildOptions
571571
preview: ResolvedPreviewOptions
572572
ssr: ResolvedSSROptions

0 commit comments

Comments
 (0)