diff --git a/src/node/server/serverPluginHmr.ts b/src/node/server/serverPluginHmr.ts index 81936a6650d614..b0050ada1b7f49 100644 --- a/src/node/server/serverPluginHmr.ts +++ b/src/node/server/serverPluginHmr.ts @@ -150,47 +150,43 @@ export const hmrPlugin: ServerPlugin = ({ } const publicPath = resolver.fileToRequest(filePath) - const importers = importerMap.get(publicPath) - if (importers) { - const hmrBoundaries = new Set() - const dirtyFiles = new Set() - dirtyFiles.add(publicPath) - - const hasDeadEnd = walkImportChain( - publicPath, - importers, - hmrBoundaries, - dirtyFiles - ) - - // record dirty files - this is used when HMR requests coming in with - // timestamp to determine what files need to be force re-fetched - hmrDirtyFilesMap.set(String(timestamp), dirtyFiles) + const importers = ensureMapEntry(importerMap, publicPath) + const hmrBoundaries = new Set() + const dirtyFiles = new Set() + dirtyFiles.add(publicPath) + + const hasDeadEnd = walkImportChain( + publicPath, + importers, + hmrBoundaries, + dirtyFiles + ) - const relativeFile = '/' + slash(path.relative(root, filePath)) - if (hasDeadEnd) { + // record dirty files - this is used when HMR requests coming in with + // timestamp to determine what files need to be force re-fetched + hmrDirtyFilesMap.set(String(timestamp), dirtyFiles) + + const relativeFile = '/' + slash(path.relative(root, filePath)) + if (hasDeadEnd) { + send({ + type: 'full-reload', + path: publicPath, + timestamp + }) + console.log(chalk.green(`[vite] `) + `page reloaded.`) + } else { + hmrBoundaries.forEach((boundary) => { + console.log( + chalk.green(`[vite:hmr] `) + + `${boundary} updated due to change in ${relativeFile}.` + ) send({ - type: 'full-reload', - path: publicPath, + type: boundary.endsWith('vue') ? 'vue-reload' : 'js-update', + path: boundary, + changeSrcPath: publicPath, timestamp }) - console.log(chalk.green(`[vite] `) + `page reloaded.`) - } else { - hmrBoundaries.forEach((boundary) => { - console.log( - chalk.green(`[vite:hmr] `) + - `${boundary} updated due to change in ${relativeFile}.` - ) - send({ - type: boundary.endsWith('vue') ? 'vue-reload' : 'js-update', - path: boundary, - changeSrcPath: publicPath, - timestamp - }) - }) - } - } else { - debugHmr(`no importers for ${publicPath}.`) + }) } }) diff --git a/src/node/server/serverPluginModuleRewrite.ts b/src/node/server/serverPluginModuleRewrite.ts index 5ded2dd48250a6..a4f64c02e80f98 100644 --- a/src/node/server/serverPluginModuleRewrite.ts +++ b/src/node/server/serverPluginModuleRewrite.ts @@ -72,10 +72,18 @@ export const moduleRewritePlugin: ServerPlugin = ({ ctx.body = rewriteCache.get(content) } else { await initLexer + // dynamic import may conatin extension-less path, + // (.e.g import(runtimePathString)) + // so we need to normalize importer to ensure it contains extension before we perform hmr analysis. + // on the other hand, static import is guaranteed to have extension + // because they must all have gone through module rewrite) + const importer = resolver.fileToRequest( + resolver.requestToFile(ctx.path) + ) ctx.body = rewriteImports( root, content!, - ctx.path, + importer, resolver, ctx.query.t )