Skip to content

Commit

Permalink
fix: support process each out dir when there are two or more (#9748)
Browse files Browse the repository at this point in the history
  • Loading branch information
qmhc committed Sep 30, 2022
1 parent 8ede2f1 commit ee3231c
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 44 deletions.
101 changes: 60 additions & 41 deletions packages/vite/src/node/build.ts
Expand Up @@ -559,28 +559,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 @@ -591,7 +593,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 @@ -610,55 +612,72 @@ 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`
const nonDuplicateDirs = new Set(outDirs)
let outside = false
if (emptyOutDir == null) {
for (const outDir of nonDuplicateDirs) {
if (
fs.existsSync(outDir) &&
!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`
)
)
)
} else if (emptyOutDir !== false) {
emptyDir(outDir, ['.git'])
outside = true
break
}
}
}
if (config.publicDir && fs.existsSync(config.publicDir)) {
copyDir(config.publicDir, outDir)
for (const outDir of nonDuplicateDirs) {
if (!outside && emptyOutDir !== false && fs.existsSync(outDir)) {
// 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'])
}
if (config.publicDir && fs.existsSync(config.publicDir)) {
copyDir(config.publicDir, outDir)
}
}
}

Expand Down
35 changes: 32 additions & 3 deletions packages/vite/src/node/utils.ts
Expand Up @@ -549,16 +549,45 @@ export function isFileReadable(filename: string): boolean {
}
}

const splitFirstDirRE = /(.+?)[\\/](.+)/

/**
* 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 {
const skipInDir: string[] = []
let nested: Map<string, string[]> | null = null
if (skip?.length) {
for (const file of skip) {
if (path.dirname(file) !== '.') {
const matched = file.match(splitFirstDirRE)
if (matched) {
nested ??= new Map()
const [, nestedDir, skipPath] = matched
let nestedSkip = nested.get(nestedDir)
if (!nestedSkip) {
nestedSkip = []
nested.set(nestedDir, nestedSkip)
}
if (!nestedSkip.includes(skipPath)) {
nestedSkip.push(skipPath)
}
}
} else {
skipInDir.push(file)
}
}
}
for (const file of fs.readdirSync(dir)) {
if (skip?.includes(file)) {
if (skipInDir.includes(file)) {
continue
}
fs.rmSync(path.resolve(dir, file), { recursive: true, force: true })
if (nested?.has(file)) {
emptyDir(path.resolve(dir, file), nested.get(file))
} else {
fs.rmSync(path.resolve(dir, file), { recursive: true, force: true })
}
}
}

Expand Down

0 comments on commit ee3231c

Please sign in to comment.