Skip to content

Commit 574c05d

Browse files
committed
refactor: extract prepareOutDir as a plugin
1 parent 82d9315 commit 574c05d

File tree

2 files changed

+119
-90
lines changed

2 files changed

+119
-90
lines changed

packages/vite/src/node/build.ts

Lines changed: 17 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import fs from 'node:fs'
21
import path from 'node:path'
32
import colors from 'picocolors'
43
import type {
@@ -33,7 +32,6 @@ import type { RollupCommonJSOptions } from 'dep-types/commonjs'
3332
import type { RollupDynamicImportVarsOptions } from 'dep-types/dynamicImportVars'
3433
import type { EsbuildTarget } from 'types/internal/esbuildOptions'
3534
import type { ChunkMetadata } from 'types/metadata'
36-
import { withTrailingSlash } from '../shared/utils'
3735
import {
3836
DEFAULT_ASSETS_INLINE_LIMIT,
3937
ESBUILD_MODULES_TARGET,
@@ -54,14 +52,11 @@ import { type TerserOptions, terserPlugin } from './plugins/terser'
5452
import {
5553
arraify,
5654
asyncFlatten,
57-
copyDir,
5855
createDebugger,
5956
displayTime,
60-
emptyDir,
6157
getPkgName,
6258
joinUrlSegments,
6359
mergeWithDefaults,
64-
normalizePath,
6560
partialEncodeURIPath,
6661
unique,
6762
} from './utils'
@@ -90,6 +85,7 @@ import {
9085
import type { Plugin } from './plugin'
9186
import type { RollupPluginHooks } from './typeUtils'
9287
import { buildOxcPlugin } from './plugins/oxc'
88+
import { prepareOutDirPlugin } from './plugins/prepareOutDir'
9389

9490
export interface BuildEnvironmentOptions {
9591
/**
@@ -486,6 +482,7 @@ export async function resolveBuildPlugins(config: ResolvedConfig): Promise<{
486482
return {
487483
pre: [
488484
completeSystemWrapPlugin(),
485+
prepareOutDirPlugin(),
489486
perEnvironmentPlugin(
490487
'vite:rollup-options-plugins',
491488
async (environment) =>
@@ -742,12 +739,6 @@ async function buildEnvironment(
742739
}
743740
}
744741

745-
const outputBuildError = (e: RollupError) => {
746-
enhanceRollupError(e)
747-
clearLine()
748-
logger.error(e.message, { error: e })
749-
}
750-
751742
const isSsrTargetWebworkerEnvironment =
752743
environment.name === 'ssr' &&
753744
environment.getTopLevelConfig().ssr?.target === 'webworker'
@@ -849,22 +840,21 @@ async function buildEnvironment(
849840
normalizedOutputs.push(buildOutputOptions(outputs))
850841
}
851842

852-
const resolvedOutDirs = getResolvedOutDirs(
853-
root,
854-
options.outDir,
855-
options.rollupOptions.output,
856-
)
857-
const emptyOutDir = resolveEmptyOutDir(
858-
options.emptyOutDir,
859-
root,
860-
resolvedOutDirs,
861-
logger,
862-
)
863-
864843
// watch file changes with rollup
865844
if (options.watch) {
866845
logger.info(colors.cyan(`\nwatching for file changes...`))
867846

847+
const resolvedOutDirs = getResolvedOutDirs(
848+
root,
849+
options.outDir,
850+
options.rollupOptions.output,
851+
)
852+
const emptyOutDir = resolveEmptyOutDir(
853+
options.emptyOutDir,
854+
root,
855+
resolvedOutDirs,
856+
logger,
857+
)
868858
const resolvedChokidarOptions = resolveChokidarOptions(
869859
// @ts-expect-error chokidar option does not exist in rolldown but used for backward compat
870860
options.watch.chokidar,
@@ -886,14 +876,14 @@ async function buildEnvironment(
886876
watcher.on('event', (event) => {
887877
if (event.code === 'BUNDLE_START') {
888878
logger.info(colors.cyan(`\nbuild started...`))
889-
if (options.write) {
890-
prepareOutDir(resolvedOutDirs, emptyOutDir, environment)
891-
}
892879
} else if (event.code === 'BUNDLE_END') {
893880
event.result.close()
894881
logger.info(colors.cyan(`built in ${event.duration}ms.`))
895882
} else if (event.code === 'ERROR') {
896-
outputBuildError(event.error)
883+
const e = event.error
884+
enhanceRollupError(e)
885+
clearLine()
886+
logger.error(e.message, { error: e })
897887
}
898888
})
899889

@@ -904,11 +894,6 @@ async function buildEnvironment(
904894
const { rolldown } = await import('rolldown')
905895
startTime = Date.now()
906896
bundle = await rolldown(rollupOptions)
907-
908-
if (options.write) {
909-
prepareOutDir(resolvedOutDirs, emptyOutDir, environment)
910-
}
911-
912897
const res: RolldownOutput[] = []
913898
for (const output of normalizedOutputs) {
914899
res.push(await bundle[options.write ? 'write' : 'generate'](output))
@@ -932,54 +917,6 @@ async function buildEnvironment(
932917
}
933918
}
934919

935-
function prepareOutDir(
936-
outDirs: Set<string>,
937-
emptyOutDir: boolean | null,
938-
environment: BuildEnvironment,
939-
) {
940-
const { publicDir } = environment.config
941-
const outDirsArray = [...outDirs]
942-
for (const outDir of outDirs) {
943-
if (emptyOutDir !== false && fs.existsSync(outDir)) {
944-
// skip those other outDirs which are nested in current outDir
945-
const skipDirs = outDirsArray
946-
.map((dir) => {
947-
const relative = path.relative(outDir, dir)
948-
if (
949-
relative &&
950-
!relative.startsWith('..') &&
951-
!path.isAbsolute(relative)
952-
) {
953-
return relative
954-
}
955-
return ''
956-
})
957-
.filter(Boolean)
958-
emptyDir(outDir, [...skipDirs, '.git'])
959-
}
960-
if (
961-
environment.config.build.copyPublicDir &&
962-
publicDir &&
963-
fs.existsSync(publicDir)
964-
) {
965-
if (!areSeparateFolders(outDir, publicDir)) {
966-
environment.logger.warn(
967-
colors.yellow(
968-
`\n${colors.bold(
969-
`(!)`,
970-
)} The public directory feature may not work correctly. outDir ${colors.white(
971-
colors.dim(outDir),
972-
)} and publicDir ${colors.white(
973-
colors.dim(publicDir),
974-
)} are not separate folders.\n`,
975-
),
976-
)
977-
}
978-
copyDir(publicDir, outDir)
979-
}
980-
}
981-
}
982-
983920
type JsExt = 'js' | 'cjs' | 'mjs'
984921

985922
function resolveOutputJsExtension(
@@ -1602,16 +1539,6 @@ export function toOutputFilePathWithoutRuntime(
16021539
export const toOutputFilePathInCss = toOutputFilePathWithoutRuntime
16031540
export const toOutputFilePathInHtml = toOutputFilePathWithoutRuntime
16041541

1605-
function areSeparateFolders(a: string, b: string) {
1606-
const na = normalizePath(a)
1607-
const nb = normalizePath(b)
1608-
return (
1609-
na !== nb &&
1610-
!na.startsWith(withTrailingSlash(nb)) &&
1611-
!nb.startsWith(withTrailingSlash(na))
1612-
)
1613-
}
1614-
16151542
export class BuildEnvironment extends BaseEnvironment {
16161543
mode = 'build' as const
16171544

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import fs from 'node:fs'
2+
import path from 'node:path'
3+
import colors from 'picocolors'
4+
import type { Plugin } from '../plugin'
5+
import { getResolvedOutDirs, resolveEmptyOutDir } from '../watch'
6+
import type { Environment } from '../environment'
7+
import { copyDir, emptyDir, normalizePath } from '../utils'
8+
import { withTrailingSlash } from '../../shared/utils'
9+
10+
export function prepareOutDirPlugin(): Plugin {
11+
const rendered = new Set<Environment>()
12+
return {
13+
name: 'vite:prepare-out-dir',
14+
options() {
15+
rendered.delete(this.environment)
16+
},
17+
renderStart: {
18+
order: 'pre',
19+
handler() {
20+
if (rendered.has(this.environment)) {
21+
return
22+
}
23+
rendered.add(this.environment)
24+
25+
const { config } = this.environment
26+
if (config.build.write) {
27+
const { root, build: options } = config
28+
const resolvedOutDirs = getResolvedOutDirs(
29+
root,
30+
options.outDir,
31+
options.rollupOptions.output,
32+
)
33+
const emptyOutDir = resolveEmptyOutDir(
34+
options.emptyOutDir,
35+
root,
36+
resolvedOutDirs,
37+
this.environment.logger,
38+
)
39+
prepareOutDir(resolvedOutDirs, emptyOutDir, this.environment)
40+
}
41+
},
42+
},
43+
}
44+
}
45+
46+
function prepareOutDir(
47+
outDirs: Set<string>,
48+
emptyOutDir: boolean | null,
49+
environment: Environment,
50+
) {
51+
const { publicDir } = environment.config
52+
const outDirsArray = [...outDirs]
53+
for (const outDir of outDirs) {
54+
if (emptyOutDir !== false && fs.existsSync(outDir)) {
55+
// skip those other outDirs which are nested in current outDir
56+
const skipDirs = outDirsArray
57+
.map((dir) => {
58+
const relative = path.relative(outDir, dir)
59+
if (
60+
relative &&
61+
!relative.startsWith('..') &&
62+
!path.isAbsolute(relative)
63+
) {
64+
return relative
65+
}
66+
return ''
67+
})
68+
.filter(Boolean)
69+
emptyDir(outDir, [...skipDirs, '.git'])
70+
}
71+
if (
72+
environment.config.build.copyPublicDir &&
73+
publicDir &&
74+
fs.existsSync(publicDir)
75+
) {
76+
if (!areSeparateFolders(outDir, publicDir)) {
77+
environment.logger.warn(
78+
colors.yellow(
79+
`\n${colors.bold(
80+
`(!)`,
81+
)} The public directory feature may not work correctly. outDir ${colors.white(
82+
colors.dim(outDir),
83+
)} and publicDir ${colors.white(
84+
colors.dim(publicDir),
85+
)} are not separate folders.\n`,
86+
),
87+
)
88+
}
89+
copyDir(publicDir, outDir)
90+
}
91+
}
92+
}
93+
94+
function areSeparateFolders(a: string, b: string) {
95+
const na = normalizePath(a)
96+
const nb = normalizePath(b)
97+
return (
98+
na !== nb &&
99+
!na.startsWith(withTrailingSlash(nb)) &&
100+
!nb.startsWith(withTrailingSlash(na))
101+
)
102+
}

0 commit comments

Comments
 (0)