Skip to content

Commit

Permalink
fix(optimizer): fix optimizer updates on new dep discovery
Browse files Browse the repository at this point in the history
- nullify stale data before re-running
- invalidate importer modules of new deps before reloading page

fix #1755
  • Loading branch information
yyx990803 committed Jan 28, 2021
1 parent 327fa71 commit b2110af
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 26 deletions.
45 changes: 37 additions & 8 deletions packages/vite/src/node/optimizer/registerMissing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,52 @@ export function createMissingImpoterRegisterFn(server: ViteDevServer) {
const { logger } = server.config
let knownOptimized = server._optimizeDepsMetadata!.optimized
let currentMissing: Record<string, string> = {}
let currentImporters = new Set<string>()
let handle: NodeJS.Timeout

let pendingResolve: (() => void) | null = null

async function rerun() {
const newDeps = currentMissing
currentMissing = {}

for (const id in knownOptimized) {
newDeps[id] = knownOptimized[id].src
}

logger.info(
chalk.yellow(`new imports encountered, updating dependencies...`),
chalk.yellow(
`new dependencies found: ${Object.keys(newDeps).join(
', '
)}, updating...`
),
{
timestamp: true
}
)

for (const id in knownOptimized) {
newDeps[id] = knownOptimized[id].src
}

try {
// Nullify previous metadata so that the resolver won't
// resolve to optimized files during the optimizer re-run
server._optimizeDepsMetadata = null

const newData = (server._optimizeDepsMetadata = await optimizeDeps(
server.config,
true,
false,
newDeps
))
knownOptimized = newData!.optimized

// Importers' cached transform results have stale imports (resolved to
// old locations) so they need to be invalidated before the page is
// reloaded.
currentImporters.forEach((importer) => {
const mod = server.moduleGraph.getModuleById(importer)
if (mod) server.moduleGraph.invalidateModule(mod)
})
currentImporters.clear()

server.ws.send({
type: 'full-reload',
path: '*'
Expand All @@ -43,20 +64,28 @@ export function createMissingImpoterRegisterFn(server: ViteDevServer) {
{ timestamp: true }
)
} finally {
server._hasPendingReload = false
pendingResolve && pendingResolve()
server._pendingReload = pendingResolve = null
}

logger.info(chalk.greenBright(`✨ dependencies updated.`), {
timestamp: true
})
}

return function registerMissingImport(id: string, resolved: string) {
return function registerMissingImport(
id: string,
resolved: string,
importer?: string
) {
if (!knownOptimized[id]) {
currentMissing[id] = resolved
if (importer) currentImporters.add(importer)
if (handle) clearTimeout(handle)
handle = setTimeout(rerun, debounceMs)
server._hasPendingReload = true
server._pendingReload = new Promise((r) => {
pendingResolve = r
})
}
}
}
32 changes: 21 additions & 11 deletions packages/vite/src/node/plugins/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,11 @@ export function resolvePlugin({
if (
(res = tryNodeResolve(
id,
importer && importer[0] === '/' && fs.existsSync(cleanUrl(importer))
? path.dirname(importer)
: root,
importer,
root,
isProduction,
isBuild,
dedupe,
root,
server
))
) {
Expand Down Expand Up @@ -300,18 +298,27 @@ export const idToPkgMap = new Map<string, PackageData>()

export function tryNodeResolve(
id: string,
basedir: string,
importer: string | undefined,
root: string,
isProduction: boolean,
isBuild = true,
dedupe?: string[],
dedupeRoot?: string,
server?: ViteDevServer
): PartialResolvedId | undefined {
const deepMatch = id.match(deepImportRE)
const pkgId = deepMatch ? deepMatch[1] || deepMatch[2] : id

if (dedupe && dedupeRoot && dedupe.includes(pkgId)) {
basedir = dedupeRoot
let basedir
if (dedupe && dedupe.includes(pkgId)) {
basedir = root
} else if (
importer &&
path.isAbsolute(importer) &&
fs.existsSync(cleanUrl(importer))
) {
basedir = path.dirname(importer)
} else {
basedir = root
}

const pkg = resolvePackageData(pkgId, basedir)
Expand All @@ -336,8 +343,11 @@ export function tryNodeResolve(
moduleSideEffects: pkg.hasSideEffects(resolved)
}
} else {
if (!resolved.includes('node_modules') || !server) {
// linked
if (
!resolved.includes('node_modules') || // linked
!server || // build
!server._optimizeDepsMetadata // optimizer resolve
) {
return { id: resolved }
}
// if we reach here, it's a valid dep import that hasn't been optimzied.
Expand All @@ -358,7 +368,7 @@ export function tryNodeResolve(
} else {
// this is a missing import.
// queue optimize-deps re-run.
server._registerMissingImport?.(id, resolved)
server._registerMissingImport?.(id, resolved, importer)
}
return { id: resolved }
}
Expand Down
8 changes: 5 additions & 3 deletions packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,13 @@ export interface ViteDevServer {
/**
* @internal
*/
_registerMissingImport: ((id: string, resolved: string) => void) | null
_registerMissingImport:
| ((id: string, resolved: string, importer?: string) => void)
| null
/**
* @internal
*/
_hasPendingReload: boolean
_pendingReload: Promise<void> | null
}

export async function createServer(
Expand Down Expand Up @@ -321,7 +323,7 @@ export async function createServer(
_ssrExternals: null,
_globImporters: {},
_registerMissingImport: null,
_hasPendingReload: false
_pendingReload: null
}

process.once('SIGTERM', async () => {
Expand Down
10 changes: 7 additions & 3 deletions packages/vite/src/node/server/moduleGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,17 @@ export class ModuleGraph {
if (mods) {
const seen = new Set<ModuleNode>()
mods.forEach((mod) => {
mod.transformResult = null
mod.ssrTransformResult = null
invalidateSSRModule(mod, seen)
this.invalidateModule(mod, seen)
})
}
}

invalidateModule(mod: ModuleNode, seen: Set<ModuleNode> = new Set()) {
mod.transformResult = null
mod.ssrTransformResult = null
invalidateSSRModule(mod, seen)
}

/**
* Update the module graph based on a module's updated imports information
* If there are dependencies that no longer have any importers, they are
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/ssr/ssrExternal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function resolveSSRExternal(
}

for (const id of deps) {
const entry = tryNodeResolve(id, root, false)?.id
const entry = tryNodeResolve(id, undefined, root, false)?.id
let requireEntry
try {
requireEntry = require.resolve(id, { paths: [root] })
Expand Down

0 comments on commit b2110af

Please sign in to comment.