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
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
96 changes: 54 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,65 @@ 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 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`
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) {
// skip those other outDirs which are nested in current outDir
const skipDirs = outDirs
.map((dir) => {
const relative = path.relative(outDir, dir)
if (
relative &&
!relative.startsWith('..') &&
!path.isAbsolute(relative)
) {
return relative
}
return ''
})
.filter(Boolean)
emptyDir(outDir, [...skipDirs, '.git'])
bluwy 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
26 changes: 23 additions & 3 deletions packages/vite/src/node/utils.ts
Expand Up @@ -534,15 +534,35 @@ export function isFileReadable(filename: string): boolean {

/**
* Delete every file and subdirectory. **The given directory must exist.**
* Pass an optional `skip` array to preserve files in the root directory.
* Pass an optional `skip` array to preserve files under the root directory.
*/
export function emptyDir(dir: string, skip?: string[]): void {
export function emptyDir(dir: string, skip: string[] = []): void {
let nested: Map<string, string[]> | null = null
skip = skip.map(slash)
for (const file of fs.readdirSync(dir)) {
if (skip?.includes(file)) {
const matched = skip.find((f) => f === file || f.startsWith(`${file}/`))
if (matched) {
if (matched !== file) {
nested ??= new Map()
let nestedSkip = nested.get(`${dir}/${file}`)
if (!nestedSkip) {
nestedSkip = []
nested.set(`${dir}/${file}`, nestedSkip)
}
const skipPath = matched.replace(`${file}/`, '')
if (!nestedSkip.includes(skipPath)) {
nestedSkip.push(skipPath)
}
qmhc marked this conversation as resolved.
Show resolved Hide resolved
}
continue
}
fs.rmSync(path.resolve(dir, file), { recursive: true, force: true })
}
if (nested?.size) {
for (const [dir, nestedSkip] of nested) {
emptyDir(dir, nestedSkip)
}
}
}

export function copyDir(srcDir: string, destDir: string): void {
Expand Down