mirror of
https://github.com/vitejs/vite.git
synced 2024-11-21 14:48:41 +00:00
refactor: use builder in build
(#18432)
This commit is contained in:
parent
19ce525b97
commit
cc61d169a4
@ -266,7 +266,7 @@ export function createHandler(input) {
|
||||
|
||||
In the CLI, calling `vite build` and `vite build --ssr` will still build the client only and ssr only environments for backward compatibility.
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
```js
|
||||
export default {
|
||||
|
@ -69,7 +69,7 @@ vite build [root]
|
||||
| `-f, --filter <filter>` | Filter debug logs (`string`) |
|
||||
| `-m, --mode <mode>` | Set env mode (`string`) |
|
||||
| `-h, --help` | Display available CLI options |
|
||||
| `--app` | Build all environments, same as `builder.entireApp` (`boolean`, experimental) |
|
||||
| `--app` | Build all environments, same as `builder: {}` (`boolean`, experimental) |
|
||||
|
||||
## Others
|
||||
|
||||
|
@ -493,35 +493,13 @@ export async function resolveBuildPlugins(config: ResolvedConfig): Promise<{
|
||||
export async function build(
|
||||
inlineConfig: InlineConfig = {},
|
||||
): Promise<RollupOutput | RollupOutput[] | RollupWatcher> {
|
||||
const patchConfig = (resolved: ResolvedConfig) => {
|
||||
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
|
||||
// we need to make override `config.build` for the current environment.
|
||||
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
|
||||
// remove the default values that shouldn't be used at all once the config is resolved
|
||||
const environmentName = resolved.build.ssr ? 'ssr' : 'client'
|
||||
;(resolved.build as ResolvedBuildOptions) = {
|
||||
...resolved.environments[environmentName].build,
|
||||
}
|
||||
}
|
||||
const config = await resolveConfigToBuild(inlineConfig, patchConfig)
|
||||
return buildWithResolvedConfig(config)
|
||||
const builder = await createBuilder(inlineConfig, true)
|
||||
const environment = Object.values(builder.environments)[0]
|
||||
if (!environment) throw new Error('No environment found')
|
||||
return builder.build(environment)
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal used to implement `vite build` for backward compatibility
|
||||
*/
|
||||
export async function buildWithResolvedConfig(
|
||||
config: ResolvedConfig,
|
||||
): Promise<RollupOutput | RollupOutput[] | RollupWatcher> {
|
||||
const environmentName = config.build.ssr ? 'ssr' : 'client'
|
||||
const environment = await config.environments[
|
||||
environmentName
|
||||
].build.createEnvironment(environmentName, config)
|
||||
await environment.init()
|
||||
return buildEnvironment(environment)
|
||||
}
|
||||
|
||||
export function resolveConfigToBuild(
|
||||
function resolveConfigToBuild(
|
||||
inlineConfig: InlineConfig = {},
|
||||
patchConfig?: (config: ResolvedConfig) => void,
|
||||
patchPlugins?: (resolvedPlugins: Plugin[]) => void,
|
||||
@ -540,7 +518,7 @@ export function resolveConfigToBuild(
|
||||
/**
|
||||
* Build an App environment, or a App library (if libraryOptions is provided)
|
||||
**/
|
||||
export async function buildEnvironment(
|
||||
async function buildEnvironment(
|
||||
environment: BuildEnvironment,
|
||||
): Promise<RollupOutput | RollupOutput[] | RollupWatcher> {
|
||||
const { root, packageCache } = environment.config
|
||||
@ -1486,7 +1464,6 @@ export interface ViteBuilder {
|
||||
export interface BuilderOptions {
|
||||
sharedConfigBuild?: boolean
|
||||
sharedPlugins?: boolean
|
||||
entireApp?: boolean
|
||||
buildApp?: (builder: ViteBuilder) => Promise<void>
|
||||
}
|
||||
|
||||
@ -1497,12 +1474,12 @@ async function defaultBuildApp(builder: ViteBuilder): Promise<void> {
|
||||
}
|
||||
|
||||
export function resolveBuilderOptions(
|
||||
options: BuilderOptions = {},
|
||||
): ResolvedBuilderOptions {
|
||||
options: BuilderOptions | undefined,
|
||||
): ResolvedBuilderOptions | undefined {
|
||||
if (!options) return
|
||||
return {
|
||||
sharedConfigBuild: options.sharedConfigBuild ?? false,
|
||||
sharedPlugins: options.sharedPlugins ?? false,
|
||||
entireApp: options.entireApp ?? false,
|
||||
buildApp: options.buildApp ?? defaultBuildApp,
|
||||
}
|
||||
}
|
||||
@ -1515,83 +1492,91 @@ export type ResolvedBuilderOptions = Required<BuilderOptions>
|
||||
*/
|
||||
export async function createBuilder(
|
||||
inlineConfig: InlineConfig = {},
|
||||
useLegacyBuilder: null | boolean = false,
|
||||
): Promise<ViteBuilder> {
|
||||
const config = await resolveConfigToBuild(inlineConfig)
|
||||
return createBuilderWithResolvedConfig(inlineConfig, config)
|
||||
}
|
||||
const patchConfig = (resolved: ResolvedConfig) => {
|
||||
if (!(useLegacyBuilder ?? !resolved.builder)) return
|
||||
|
||||
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
|
||||
// we need to make override `config.build` for the current environment.
|
||||
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
|
||||
// remove the default values that shouldn't be used at all once the config is resolved
|
||||
const environmentName = resolved.build.ssr ? 'ssr' : 'client'
|
||||
;(resolved.build as ResolvedBuildOptions) = {
|
||||
...resolved.environments[environmentName].build,
|
||||
}
|
||||
}
|
||||
const config = await resolveConfigToBuild(inlineConfig, patchConfig)
|
||||
useLegacyBuilder ??= !config.builder
|
||||
const configBuilder = config.builder ?? resolveBuilderOptions({})!
|
||||
|
||||
/**
|
||||
* Used to implement the `vite build` command without resolving the config twice
|
||||
* @internal
|
||||
*/
|
||||
export async function createBuilderWithResolvedConfig(
|
||||
inlineConfig: InlineConfig,
|
||||
config: ResolvedConfig,
|
||||
): Promise<ViteBuilder> {
|
||||
const environments: Record<string, BuildEnvironment> = {}
|
||||
|
||||
const builder: ViteBuilder = {
|
||||
environments,
|
||||
config,
|
||||
async buildApp() {
|
||||
return config.builder.buildApp(builder)
|
||||
return configBuilder.buildApp(builder)
|
||||
},
|
||||
async build(environment: BuildEnvironment) {
|
||||
return buildEnvironment(environment)
|
||||
},
|
||||
}
|
||||
|
||||
for (const environmentName of Object.keys(config.environments)) {
|
||||
// We need to resolve the config again so we can properly merge options
|
||||
// and get a new set of plugins for each build environment. The ecosystem
|
||||
// expects plugins to be run for the same environment once they are created
|
||||
// and to process a single bundle at a time (contrary to dev mode where
|
||||
// plugins are built to handle multiple environments concurrently).
|
||||
let environmentConfig = config
|
||||
if (!config.builder.sharedConfigBuild) {
|
||||
const patchConfig = (resolved: ResolvedConfig) => {
|
||||
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
|
||||
// we need to make override `config.build` for the current environment.
|
||||
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
|
||||
// remove the default values that shouldn't be used at all once the config is resolved
|
||||
;(resolved.build as ResolvedBuildOptions) = {
|
||||
...resolved.environments[environmentName].build,
|
||||
async function setupEnvironment(name: string, config: ResolvedConfig) {
|
||||
const environment = await config.build.createEnvironment(name, config)
|
||||
await environment.init()
|
||||
environments[name] = environment
|
||||
}
|
||||
|
||||
if (useLegacyBuilder) {
|
||||
await setupEnvironment(config.build.ssr ? 'ssr' : 'client', config)
|
||||
} else {
|
||||
for (const environmentName of Object.keys(config.environments)) {
|
||||
// We need to resolve the config again so we can properly merge options
|
||||
// and get a new set of plugins for each build environment. The ecosystem
|
||||
// expects plugins to be run for the same environment once they are created
|
||||
// and to process a single bundle at a time (contrary to dev mode where
|
||||
// plugins are built to handle multiple environments concurrently).
|
||||
let environmentConfig = config
|
||||
if (!configBuilder.sharedConfigBuild) {
|
||||
const patchConfig = (resolved: ResolvedConfig) => {
|
||||
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
|
||||
// we need to make override `config.build` for the current environment.
|
||||
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
|
||||
// remove the default values that shouldn't be used at all once the config is resolved
|
||||
;(resolved.build as ResolvedBuildOptions) = {
|
||||
...resolved.environments[environmentName].build,
|
||||
}
|
||||
}
|
||||
}
|
||||
const patchPlugins = (resolvedPlugins: Plugin[]) => {
|
||||
// Force opt-in shared plugins
|
||||
let j = 0
|
||||
for (let i = 0; i < resolvedPlugins.length; i++) {
|
||||
const environmentPlugin = resolvedPlugins[i]
|
||||
if (
|
||||
config.builder.sharedPlugins ||
|
||||
environmentPlugin.sharedDuringBuild
|
||||
) {
|
||||
for (let k = j; k < config.plugins.length; k++) {
|
||||
if (environmentPlugin.name === config.plugins[k].name) {
|
||||
resolvedPlugins[i] = config.plugins[k]
|
||||
j = k + 1
|
||||
break
|
||||
const patchPlugins = (resolvedPlugins: Plugin[]) => {
|
||||
// Force opt-in shared plugins
|
||||
let j = 0
|
||||
for (let i = 0; i < resolvedPlugins.length; i++) {
|
||||
const environmentPlugin = resolvedPlugins[i]
|
||||
if (
|
||||
configBuilder.sharedPlugins ||
|
||||
environmentPlugin.sharedDuringBuild
|
||||
) {
|
||||
for (let k = j; k < config.plugins.length; k++) {
|
||||
if (environmentPlugin.name === config.plugins[k].name) {
|
||||
resolvedPlugins[i] = config.plugins[k]
|
||||
j = k + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
environmentConfig = await resolveConfigToBuild(
|
||||
inlineConfig,
|
||||
patchConfig,
|
||||
patchPlugins,
|
||||
)
|
||||
}
|
||||
environmentConfig = await resolveConfigToBuild(
|
||||
inlineConfig,
|
||||
patchConfig,
|
||||
patchPlugins,
|
||||
)
|
||||
|
||||
await setupEnvironment(environmentName, environmentConfig)
|
||||
}
|
||||
|
||||
const environment = await environmentConfig.build.createEnvironment(
|
||||
environmentName,
|
||||
environmentConfig,
|
||||
)
|
||||
|
||||
await environment.init()
|
||||
|
||||
environments[environmentName] = environment
|
||||
}
|
||||
|
||||
return builder
|
||||
|
@ -4,13 +4,13 @@ import { performance } from 'node:perf_hooks'
|
||||
import { cac } from 'cac'
|
||||
import colors from 'picocolors'
|
||||
import { VERSION } from './constants'
|
||||
import type { BuildEnvironmentOptions, ResolvedBuildOptions } from './build'
|
||||
import type { BuildEnvironmentOptions } from './build'
|
||||
import type { ServerOptions } from './server'
|
||||
import type { CLIShortcut } from './shortcuts'
|
||||
import type { LogLevel } from './logger'
|
||||
import { createLogger } from './logger'
|
||||
import { resolveConfig } from './config'
|
||||
import type { InlineConfig, ResolvedConfig } from './config'
|
||||
import type { InlineConfig } from './config'
|
||||
|
||||
const cli = cac('vite')
|
||||
|
||||
@ -285,14 +285,14 @@ cli
|
||||
`[boolean] force empty outDir when it's outside of root`,
|
||||
)
|
||||
.option('-w, --watch', `[boolean] rebuilds when modules have changed on disk`)
|
||||
.option('--app', `[boolean] same as builder.entireApp`)
|
||||
.option('--app', `[boolean] same as \`builder: {}\``)
|
||||
.action(
|
||||
async (
|
||||
root: string,
|
||||
options: BuildEnvironmentOptions & BuilderCLIOptions & GlobalCLIOptions,
|
||||
) => {
|
||||
filterDuplicateOptions(options)
|
||||
const build = await import('./build')
|
||||
const { createBuilder } = await import('./build')
|
||||
|
||||
const buildOptions: BuildEnvironmentOptions = cleanGlobalCLIOptions(
|
||||
cleanBuilderCLIOptions(options),
|
||||
@ -307,36 +307,10 @@ cli
|
||||
logLevel: options.logLevel,
|
||||
clearScreen: options.clearScreen,
|
||||
build: buildOptions,
|
||||
...(options.app ? { builder: { entireApp: true } } : {}),
|
||||
}
|
||||
const patchConfig = (resolved: ResolvedConfig) => {
|
||||
if (resolved.builder.entireApp) {
|
||||
return
|
||||
}
|
||||
// Until the ecosystem updates to use `environment.config.build` instead of `config.build`,
|
||||
// we need to make override `config.build` for the current environment.
|
||||
// We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later
|
||||
// remove the default values that shouldn't be used at all once the config is resolved
|
||||
const environmentName = resolved.build.ssr ? 'ssr' : 'client'
|
||||
;(resolved.build as ResolvedBuildOptions) = {
|
||||
...resolved.environments[environmentName].build,
|
||||
}
|
||||
}
|
||||
const config = await build.resolveConfigToBuild(
|
||||
inlineConfig,
|
||||
patchConfig,
|
||||
)
|
||||
|
||||
if (config.builder.entireApp) {
|
||||
const builder = await build.createBuilderWithResolvedConfig(
|
||||
inlineConfig,
|
||||
config,
|
||||
)
|
||||
await builder.buildApp()
|
||||
} else {
|
||||
// Single environment (client or ssr) build or library mode build
|
||||
await build.buildWithResolvedConfig(config)
|
||||
...(options.app ? { builder: {} } : {}),
|
||||
}
|
||||
const builder = await createBuilder(inlineConfig, null)
|
||||
await builder.buildApp()
|
||||
} catch (e) {
|
||||
createLogger(options.logLevel).error(
|
||||
colors.red(`error during build:\n${e.stack}`),
|
||||
|
@ -566,7 +566,7 @@ export type ResolvedConfig = Readonly<
|
||||
server: ResolvedServerOptions
|
||||
dev: ResolvedDevEnvironmentOptions
|
||||
/** @experimental */
|
||||
builder: ResolvedBuilderOptions
|
||||
builder: ResolvedBuilderOptions | undefined
|
||||
build: ResolvedBuildOptions
|
||||
preview: ResolvedPreviewOptions
|
||||
ssr: ResolvedSSROptions
|
||||
|
Loading…
Reference in New Issue
Block a user