Skip to content

Commit

Permalink
feat: scan free dev server (#8319)
Browse files Browse the repository at this point in the history
  • Loading branch information
patak-dev committed May 27, 2022
1 parent 1dbc7cc commit 3f742b6
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 12 deletions.
7 changes: 7 additions & 0 deletions packages/vite/src/node/optimizer/index.ts
Expand Up @@ -62,6 +62,13 @@ export interface DepOptimizationOptions {
* vite project root. This will overwrite default entries inference.
*/
entries?: string | string[]
/**
* Enable esbuild based scan phase, to get back to the optimized deps discovery
* strategy used in Vite v2
* @default false
* @experimental
*/
devScan?: boolean
/**
* Force optimize listed dependencies (must be resolvable import paths,
* cannot be globs).
Expand Down
15 changes: 11 additions & 4 deletions packages/vite/src/node/optimizer/optimizer.ts
Expand Up @@ -46,6 +46,8 @@ export async function initDepsOptimizer(
const { logger } = config
const isBuild = config.command === 'build'

const scan = config.command !== 'build' && config.optimizeDeps.devScan

const sessionTimestamp = Date.now().toString()

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

// Debounced rerun, let other missing dependencies be discovered before
// the running next optimizeDeps
if (!isBuild) {
// Until the first optimize run is called, avoid triggering processing
// We'll wait until the user codebase is eagerly processed by Vite so
// we can get a list of every missing dependency before giving to the
// browser a dependency that may be outdated, thus avoiding full page reloads

if (scan || firstRunCalled) {
// Debounced rerun, let other missing dependencies be discovered before
// the running next optimizeDeps
debouncedProcessing()
}

Expand Down
17 changes: 12 additions & 5 deletions packages/vite/src/node/plugins/importAnalysis.ts
Expand Up @@ -49,7 +49,10 @@ import {
optimizedDepNeedsInterop
} from '../optimizer'
import { checkPublicFile } from './asset'
import { ERR_OUTDATED_OPTIMIZED_DEP } from './optimizedDeps'
import {
ERR_OUTDATED_OPTIMIZED_DEP,
delayDepsOptimizerUntil
} from './optimizedDeps'
import { isCSSRequest, isDirectCSSRequest } from './css'

const isDebug = !!process.env.DEBUG
Expand Down Expand Up @@ -183,7 +186,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
let s: MagicString | undefined
const str = () => s || (s = new MagicString(source))
const importedUrls = new Set<string>()
const staticImportedUrls = new Set<string>()
const staticImportedUrls = new Set<{ url: string; id: string }>()
const acceptedUrls = new Set<{
url: string
start: number
Expand Down Expand Up @@ -462,7 +465,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
importedUrls.add(urlWithoutBase)
if (!isDynamicImport) {
// for pre-transforming
staticImportedUrls.add(urlWithoutBase)
staticImportedUrls.add({ url: urlWithoutBase, id: resolvedId })
}
} else if (!importer.startsWith(clientDir) && !ssr) {
// check @vite-ignore which suppresses dynamic import warning
Expand Down Expand Up @@ -601,20 +604,24 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
)

// pre-transform known direct imports
// TODO: we should also crawl dynamic imports
if (config.server.preTransformRequests && staticImportedUrls.size) {
staticImportedUrls.forEach((url) => {
staticImportedUrls.forEach(({ url, id }) => {
url = unwrapId(removeImportQuery(url)).replace(
NULL_BYTE_PLACEHOLDER,
'\0'
)
transformRequest(url, server, { ssr }).catch((e) => {
const request = transformRequest(url, server, { ssr }).catch((e) => {
if (e?.code === ERR_OUTDATED_OPTIMIZED_DEP) {
// This are expected errors
return
}
// Unexpected error, log the issue but avoid an unhandled exception
config.logger.error(e.message)
})
if (!config.optimizeDeps.devScan) {
delayDepsOptimizerUntil(config, id, () => request)
}
})
}

Expand Down
22 changes: 19 additions & 3 deletions packages/vite/src/node/plugins/optimizedDeps.ts
Expand Up @@ -16,7 +16,7 @@ const debug = createDebugger('vite:optimize-deps')
const runOptimizerIfIdleAfterMs = 100

interface RunProcessingInfo {
ids: { id: string; done: () => Promise<void> }[]
ids: { id: string; done: () => Promise<any> }[]
seenIds: Set<string>
workersSources: Set<string>
waitingOn: string | undefined
Expand Down Expand Up @@ -51,10 +51,10 @@ export function registerWorkersSource(config: ResolvedConfig, id: string) {
}
}

function delayDepsOptimizerUntil(
export function delayDepsOptimizerUntil(
config: ResolvedConfig,
id: string,
done: () => Promise<void>
done: () => Promise<any>
) {
const info = getRunProcessingInfo(config)
if (
Expand Down Expand Up @@ -98,6 +98,22 @@ export function optimizedDepsPlugin(config: ResolvedConfig): Plugin {
return {
name: 'vite:optimized-deps',

buildStart() {
if (!config.isWorker) {
initRunProcessingInfo(config)
}
},

async resolveId(id) {
if (getDepsOptimizer(config)?.isOptimizedDepFile(id)) {
return id
}
},

// this.load({ id }) isn't implemented in PluginContainer
// The logic to register an id to wait until it is processed
// is in importAnalysis, see call to delayDepsOptimizerUntil

async load(id) {
const depsOptimizer = getDepsOptimizer(config)
if (depsOptimizer?.isOptimizedDepFile(id)) {
Expand Down

0 comments on commit 3f742b6

Please sign in to comment.