Skip to content

Commit 3f742b6

Browse files
authored
feat: scan free dev server (#8319)
1 parent 1dbc7cc commit 3f742b6

File tree

4 files changed

+49
-12
lines changed

4 files changed

+49
-12
lines changed

packages/vite/src/node/optimizer/index.ts

+7
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ export interface DepOptimizationOptions {
6262
* vite project root. This will overwrite default entries inference.
6363
*/
6464
entries?: string | string[]
65+
/**
66+
* Enable esbuild based scan phase, to get back to the optimized deps discovery
67+
* strategy used in Vite v2
68+
* @default false
69+
* @experimental
70+
*/
71+
devScan?: boolean
6572
/**
6673
* Force optimize listed dependencies (must be resolvable import paths,
6774
* cannot be globs).

packages/vite/src/node/optimizer/optimizer.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export async function initDepsOptimizer(
4646
const { logger } = config
4747
const isBuild = config.command === 'build'
4848

49+
const scan = config.command !== 'build' && config.optimizeDeps.devScan
50+
4951
const sessionTimestamp = Date.now().toString()
5052

5153
const cachedMetadata = loadCachedDepOptimizationMetadata(config)
@@ -100,7 +102,7 @@ export async function initDepsOptimizer(
100102
// If there wasn't a cache or it is outdated, we need to prepare a first run
101103
let firstRunCalled = !!cachedMetadata
102104
if (!cachedMetadata) {
103-
if (isBuild) {
105+
if (!scan) {
104106
// Initialize discovered deps with manually added optimizeDeps.include info
105107
const discovered = await initialProjectDependencies(
106108
config,
@@ -460,9 +462,14 @@ export async function initDepsOptimizer(
460462
exportsData: extractExportsData(resolved, config)
461463
})
462464

463-
// Debounced rerun, let other missing dependencies be discovered before
464-
// the running next optimizeDeps
465-
if (!isBuild) {
465+
// Until the first optimize run is called, avoid triggering processing
466+
// We'll wait until the user codebase is eagerly processed by Vite so
467+
// we can get a list of every missing dependency before giving to the
468+
// browser a dependency that may be outdated, thus avoiding full page reloads
469+
470+
if (scan || firstRunCalled) {
471+
// Debounced rerun, let other missing dependencies be discovered before
472+
// the running next optimizeDeps
466473
debouncedProcessing()
467474
}
468475

packages/vite/src/node/plugins/importAnalysis.ts

+12-5
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ import {
4949
optimizedDepNeedsInterop
5050
} from '../optimizer'
5151
import { checkPublicFile } from './asset'
52-
import { ERR_OUTDATED_OPTIMIZED_DEP } from './optimizedDeps'
52+
import {
53+
ERR_OUTDATED_OPTIMIZED_DEP,
54+
delayDepsOptimizerUntil
55+
} from './optimizedDeps'
5356
import { isCSSRequest, isDirectCSSRequest } from './css'
5457

5558
const isDebug = !!process.env.DEBUG
@@ -183,7 +186,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
183186
let s: MagicString | undefined
184187
const str = () => s || (s = new MagicString(source))
185188
const importedUrls = new Set<string>()
186-
const staticImportedUrls = new Set<string>()
189+
const staticImportedUrls = new Set<{ url: string; id: string }>()
187190
const acceptedUrls = new Set<{
188191
url: string
189192
start: number
@@ -462,7 +465,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
462465
importedUrls.add(urlWithoutBase)
463466
if (!isDynamicImport) {
464467
// for pre-transforming
465-
staticImportedUrls.add(urlWithoutBase)
468+
staticImportedUrls.add({ url: urlWithoutBase, id: resolvedId })
466469
}
467470
} else if (!importer.startsWith(clientDir) && !ssr) {
468471
// check @vite-ignore which suppresses dynamic import warning
@@ -601,20 +604,24 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
601604
)
602605

603606
// pre-transform known direct imports
607+
// TODO: we should also crawl dynamic imports
604608
if (config.server.preTransformRequests && staticImportedUrls.size) {
605-
staticImportedUrls.forEach((url) => {
609+
staticImportedUrls.forEach(({ url, id }) => {
606610
url = unwrapId(removeImportQuery(url)).replace(
607611
NULL_BYTE_PLACEHOLDER,
608612
'\0'
609613
)
610-
transformRequest(url, server, { ssr }).catch((e) => {
614+
const request = transformRequest(url, server, { ssr }).catch((e) => {
611615
if (e?.code === ERR_OUTDATED_OPTIMIZED_DEP) {
612616
// This are expected errors
613617
return
614618
}
615619
// Unexpected error, log the issue but avoid an unhandled exception
616620
config.logger.error(e.message)
617621
})
622+
if (!config.optimizeDeps.devScan) {
623+
delayDepsOptimizerUntil(config, id, () => request)
624+
}
618625
})
619626
}
620627

packages/vite/src/node/plugins/optimizedDeps.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const debug = createDebugger('vite:optimize-deps')
1616
const runOptimizerIfIdleAfterMs = 100
1717

1818
interface RunProcessingInfo {
19-
ids: { id: string; done: () => Promise<void> }[]
19+
ids: { id: string; done: () => Promise<any> }[]
2020
seenIds: Set<string>
2121
workersSources: Set<string>
2222
waitingOn: string | undefined
@@ -51,10 +51,10 @@ export function registerWorkersSource(config: ResolvedConfig, id: string) {
5151
}
5252
}
5353

54-
function delayDepsOptimizerUntil(
54+
export function delayDepsOptimizerUntil(
5555
config: ResolvedConfig,
5656
id: string,
57-
done: () => Promise<void>
57+
done: () => Promise<any>
5858
) {
5959
const info = getRunProcessingInfo(config)
6060
if (
@@ -98,6 +98,22 @@ export function optimizedDepsPlugin(config: ResolvedConfig): Plugin {
9898
return {
9999
name: 'vite:optimized-deps',
100100

101+
buildStart() {
102+
if (!config.isWorker) {
103+
initRunProcessingInfo(config)
104+
}
105+
},
106+
107+
async resolveId(id) {
108+
if (getDepsOptimizer(config)?.isOptimizedDepFile(id)) {
109+
return id
110+
}
111+
},
112+
113+
// this.load({ id }) isn't implemented in PluginContainer
114+
// The logic to register an id to wait until it is processed
115+
// is in importAnalysis, see call to delayDepsOptimizerUntil
116+
101117
async load(id) {
102118
const depsOptimizer = getDepsOptimizer(config)
103119
if (depsOptimizer?.isOptimizedDepFile(id)) {

0 commit comments

Comments
 (0)