Skip to content

Commit

Permalink
fix: don't add outDirs to watch.ignored if emptyOutDir is false (#16453)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Apr 18, 2024
1 parent 11444dc commit 6a127d6
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 39 deletions.
55 changes: 25 additions & 30 deletions packages/vite/src/node/build.ts
Expand Up @@ -51,7 +51,11 @@ import { ssrManifestPlugin } from './ssr/ssrManifestPlugin'
import { loadFallbackPlugin } from './plugins/loadFallback'
import { findNearestPackageData } from './packages'
import type { PackageCache } from './packages'
import { resolveChokidarOptions } from './watch'
import {
getResolvedOutDirs,
resolveChokidarOptions,
resolveEmptyOutDir,
} from './watch'
import { completeSystemWrapPlugin } from './plugins/completeSystemWrap'
import { mergeConfig } from './publicUtils'
import { webWorkerPostPlugin } from './plugins/worker'
Expand Down Expand Up @@ -655,7 +659,17 @@ export async function build(
normalizedOutputs.push(buildOutputOptions(outputs))
}

const outDirs = normalizedOutputs.map(({ dir }) => resolve(dir!))
const resolvedOutDirs = getResolvedOutDirs(
config.root,
options.outDir,
options.rollupOptions?.output,
)
const emptyOutDir = resolveEmptyOutDir(
options.emptyOutDir,
config.root,
resolvedOutDirs,
config.logger,
)

// watch file changes with rollup
if (config.build.watch) {
Expand All @@ -664,6 +678,8 @@ export async function build(
const resolvedChokidarOptions = resolveChokidarOptions(
config,
config.build.watch.chokidar,
resolvedOutDirs,
emptyOutDir,
)

const { watch } = await import('rollup')
Expand All @@ -680,7 +696,7 @@ export async function build(
if (event.code === 'BUNDLE_START') {
config.logger.info(colors.cyan(`\nbuild started...`))
if (options.write) {
prepareOutDir(outDirs, options.emptyOutDir, config)
prepareOutDir(resolvedOutDirs, emptyOutDir, config)
}
} else if (event.code === 'BUNDLE_END') {
event.result.close()
Expand All @@ -699,7 +715,7 @@ export async function build(
bundle = await rollup(rollupOptions)

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

const res: RollupOutput[] = []
Expand All @@ -726,36 +742,15 @@ export async function build(
}

function prepareOutDir(
outDirs: string[],
outDirs: Set<string>,
emptyOutDir: boolean | null,
config: ResolvedConfig,
) {
const nonDuplicateDirs = new Set(outDirs)
let outside = false
if (emptyOutDir == null) {
for (const outDir of nonDuplicateDirs) {
if (
fs.existsSync(outDir) &&
!normalizePath(outDir).startsWith(withTrailingSlash(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`,
),
)
outside = true
break
}
}
}
for (const outDir of nonDuplicateDirs) {
if (!outside && emptyOutDir !== false && fs.existsSync(outDir)) {
const outDirsArray = [...outDirs]
for (const outDir of outDirs) {
if (emptyOutDir !== false && fs.existsSync(outDir)) {
// skip those other outDirs which are nested in current outDir
const skipDirs = outDirs
const skipDirs = outDirsArray
.map((dir) => {
const relative = path.relative(outDir, dir)
if (
Expand Down
30 changes: 25 additions & 5 deletions packages/vite/src/node/server/index.ts
Expand Up @@ -47,7 +47,12 @@ import type { BindCLIShortcutsOptions } from '../shortcuts'
import { CLIENT_DIR, DEFAULT_DEV_PORT } from '../constants'
import type { Logger } from '../logger'
import { printServerUrls } from '../logger'
import { createNoopWatcher, resolveChokidarOptions } from '../watch'
import {
createNoopWatcher,
getResolvedOutDirs,
resolveChokidarOptions,
resolveEmptyOutDir,
} from '../watch'
import { initPublicFiles } from '../publicDir'
import { getEnvFilesForMode } from '../env'
import type { FetchResult } from '../../runtime/types'
Expand Down Expand Up @@ -428,10 +433,25 @@ export async function _createServer(
const httpsOptions = await resolveHttpsConfig(config.server.https)
const { middlewareMode } = serverConfig

const resolvedWatchOptions = resolveChokidarOptions(config, {
disableGlobbing: true,
...serverConfig.watch,
})
const resolvedOutDirs = getResolvedOutDirs(
config.root,
config.build.outDir,
config.build.rollupOptions?.output,
)
const emptyOutDir = resolveEmptyOutDir(
config.build.emptyOutDir,
config.root,
resolvedOutDirs,
)
const resolvedWatchOptions = resolveChokidarOptions(
config,
{
disableGlobbing: true,
...serverConfig.watch,
},
resolvedOutDirs,
emptyOutDir,
)

const middlewares = connect() as Connect.Server
const httpServer = middlewareMode
Expand Down
54 changes: 50 additions & 4 deletions packages/vite/src/node/watch.ts
Expand Up @@ -2,12 +2,58 @@ import { EventEmitter } from 'node:events'
import path from 'node:path'
import glob from 'fast-glob'
import type { FSWatcher, WatchOptions } from 'dep-types/chokidar'
import { arraify } from './utils'
import type { ResolvedConfig } from '.'
import type { OutputOptions } from 'rollup'
import * as colors from 'picocolors'
import { withTrailingSlash } from '../shared/utils'
import { arraify, normalizePath } from './utils'
import type { ResolvedConfig } from './config'
import type { Logger } from './logger'

export function getResolvedOutDirs(
root: string,
outDir: string,
outputOptions: OutputOptions[] | OutputOptions | undefined,
): Set<string> {
const resolvedOutDir = path.resolve(root, outDir)
if (!outputOptions) return new Set([resolvedOutDir])

return new Set(
arraify(outputOptions).map(({ dir }) =>
dir ? path.resolve(root, dir) : resolvedOutDir,
),
)
}

export function resolveEmptyOutDir(
emptyOutDir: boolean | null,
root: string,
outDirs: Set<string>,
logger?: Logger,
): boolean {
if (emptyOutDir != null) return emptyOutDir

for (const outDir of outDirs) {
if (!normalizePath(outDir).startsWith(withTrailingSlash(root))) {
// warn if outDir is outside of root
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`,
),
)
return false
}
}
return true
}

export function resolveChokidarOptions(
config: ResolvedConfig,
options: WatchOptions | undefined,
resolvedOutDirs: Set<string>,
emptyOutDir: boolean,
): WatchOptions {
const { ignored: ignoredList, ...otherOptions } = options ?? {}
const ignored: WatchOptions['ignored'] = [
Expand All @@ -17,9 +63,9 @@ export function resolveChokidarOptions(
glob.escapePath(config.cacheDir) + '/**',
...arraify(ignoredList || []),
]
if (config.build.outDir) {
if (emptyOutDir) {
ignored.push(
glob.escapePath(path.resolve(config.root, config.build.outDir)) + '/**',
...[...resolvedOutDirs].map((outDir) => glob.escapePath(outDir) + '/**'),
)
}

Expand Down

0 comments on commit 6a127d6

Please sign in to comment.