Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: support process each out dir when there are two or more #9748

Merged
merged 8 commits into from Sep 30, 2022
106 changes: 64 additions & 42 deletions packages/vite/src/node/build.ts
Expand Up @@ -491,28 +491,30 @@ async function doBuild(
libOptions,
config.logger
)
const normalizedOutputs: OutputOptions[] = []

if (Array.isArray(outputs)) {
for (const resolvedOutput of outputs) {
normalizedOutputs.push(buildOutputOptions(resolvedOutput))
}
} else {
normalizedOutputs.push(buildOutputOptions(outputs))
}

const outDirs = normalizedOutputs.map(({ dir }) => resolve(dir!))

// watch file changes with rollup
if (config.build.watch) {
config.logger.info(colors.cyan(`\nwatching for file changes...`))

const output: OutputOptions[] = []
if (Array.isArray(outputs)) {
for (const resolvedOutput of outputs) {
output.push(buildOutputOptions(resolvedOutput))
}
} else {
output.push(buildOutputOptions(outputs))
}

const resolvedChokidarOptions = resolveChokidarOptions(
config.build.watch.chokidar
)

const { watch } = await import('rollup')
const watcher = watch({
...rollupOptions,
output,
output: normalizedOutputs,
watch: {
...config.build.watch,
chokidar: resolvedChokidarOptions
Expand All @@ -523,7 +525,7 @@ async function doBuild(
if (event.code === 'BUNDLE_START') {
config.logger.info(colors.cyan(`\nbuild started...`))
if (options.write) {
prepareOutDir(outDir, options.emptyOutDir, config)
prepareOutDir(outDirs, options.emptyOutDir, config)
}
} else if (event.code === 'BUNDLE_END') {
event.result.close()
Expand All @@ -542,55 +544,75 @@ async function doBuild(
parallelBuilds.push(bundle)

const generate = (output: OutputOptions = {}) => {
return bundle[options.write ? 'write' : 'generate'](
buildOutputOptions(output)
)
return bundle[options.write ? 'write' : 'generate'](output)
}

if (options.write) {
prepareOutDir(outDir, options.emptyOutDir, config)
prepareOutDir(outDirs, options.emptyOutDir, config)
}

if (Array.isArray(outputs)) {
const res = []
for (const output of outputs) {
res.push(await generate(output))
}
return res
} else {
return await generate(outputs)
const res = []
for (const output of normalizedOutputs) {
res.push(await generate(output))
}
return Array.isArray(outputs) ? res : res[0]
} catch (e) {
outputBuildError(e)
throw e
}
}

function parseShouldEmptyDirs(outDirs: string[]) {
const sortedOutDirs = Array.from(new Set(outDirs))
.filter(Boolean)
.sort((p, n) => p.length - n.length)
const removedIndex = new Set<number>()

// if there have dirs like ['a/b/c', 'b/c', 'c'], only the `a/b/c` should be emptied
for (let i = 0; i < sortedOutDirs.length - 1; ++i) {
if (removedIndex.has(i)) continue

for (let j = i + 1; j < sortedOutDirs.length; ++j) {
if (removedIndex.has(j)) continue

if (sortedOutDirs[i].includes(sortedOutDirs[j])) {
removedIndex.add(j)
}
}
}

return sortedOutDirs.filter((_, i) => !removedIndex.has(i))
}

function prepareOutDir(
outDir: string,
outDirs: string[],
emptyOutDir: boolean | null,
config: ResolvedConfig
) {
if (fs.existsSync(outDir)) {
if (
emptyOutDir == null &&
!normalizePath(outDir).startsWith(config.root + '/')
) {
// warn if outDir is outside of root
config.logger.warn(
colors.yellow(
`\n${colors.bold(`(!)`)} outDir ${colors.white(
colors.dim(outDir)
)} is not inside project root and will not be emptied.\n` +
`Use --emptyOutDir to override.\n`
const shouldEmptyDirs = parseShouldEmptyDirs(outDirs)

for (const outDir of outDirs) {
sapphi-red marked this conversation as resolved.
Show resolved Hide resolved
if (fs.existsSync(outDir)) {
if (
emptyOutDir == null &&
!normalizePath(outDir).startsWith(config.root + '/')
) {
// warn if outDir is outside of root
config.logger.warn(
colors.yellow(
`\n${colors.bold(`(!)`)} outDir ${colors.white(
colors.dim(outDir)
)} is not inside project root and will not be emptied.\n` +
`Use --emptyOutDir to override.\n`
)
)
qmhc marked this conversation as resolved.
Show resolved Hide resolved
)
} else if (emptyOutDir !== false) {
emptyDir(outDir, ['.git'])
} else if (emptyOutDir !== false && shouldEmptyDirs.includes(outDir)) {
emptyDir(outDir, ['.git'])
qmhc marked this conversation as resolved.
Show resolved Hide resolved
}
}
if (config.publicDir && fs.existsSync(config.publicDir)) {
copyDir(config.publicDir, outDir)
}
qmhc marked this conversation as resolved.
Show resolved Hide resolved
}
if (config.publicDir && fs.existsSync(config.publicDir)) {
copyDir(config.publicDir, outDir)
}
}

Expand Down