HMR hoisted scripts (#3336)
* HMR hoisted scripts * Add to the dep graph * Remove example change * Adds changeset * Fix markdown test
This commit is contained in:
parent
3bb07a01e0
commit
ccea6a0a1a
5 changed files with 42 additions and 9 deletions
5
.changeset/happy-wasps-check.md
Normal file
5
.changeset/happy-wasps-check.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fixes HMR of hoisted script tags
|
|
@ -10,4 +10,4 @@
|
|||
<body>
|
||||
<h1>Astro</h1>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -68,6 +68,7 @@ export async function handleHotUpdate(ctx: HmrContext, config: AstroConfig, logg
|
|||
filtered.add(mod);
|
||||
files.add(mod.file);
|
||||
}
|
||||
|
||||
for (const imp of mod.importers) {
|
||||
if (imp.file && isCached(config, imp.file)) {
|
||||
filtered.add(imp);
|
||||
|
@ -85,6 +86,15 @@ export async function handleHotUpdate(ctx: HmrContext, config: AstroConfig, logg
|
|||
// Bugfix: sometimes style URLs get normalized and end with `lang.css=`
|
||||
// These will cause full reloads, so filter them out here
|
||||
const mods = ctx.modules.filter((m) => !m.url.endsWith('='));
|
||||
|
||||
// Add hoisted scripts so these get invalidated
|
||||
for(const mod of mods) {
|
||||
for(const imp of mod.importedModules) {
|
||||
if(imp.id?.includes('?astro&type=script')) {
|
||||
mods.push(imp);
|
||||
}
|
||||
}
|
||||
}
|
||||
const isSelfAccepting = mods.every((m) => m.isSelfAccepting || m.url.endsWith('.svelte'));
|
||||
|
||||
const file = ctx.file.replace(config.root.pathname, '/');
|
||||
|
|
|
@ -126,6 +126,12 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu
|
|||
if (typeof query.index === 'undefined') {
|
||||
throw new Error(`Requests for hoisted scripts must include an index`);
|
||||
}
|
||||
// HMR hoisted script only exists to make them appear in the module graph.
|
||||
if(opts?.ssr) {
|
||||
return {
|
||||
code: `/* client hoisted script, empty in SSR: ${id} */`
|
||||
};
|
||||
}
|
||||
|
||||
const transformResult = await cachedCompilation(config, filename, source, viteTransform, {
|
||||
ssr: Boolean(opts?.ssr),
|
||||
|
@ -182,17 +188,28 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu
|
|||
while ((match = pattern.exec(metadata)?.[1])) {
|
||||
deps.add(match);
|
||||
}
|
||||
// // import.meta.hot.accept(["${id}", "${Array.from(deps).join('","')}"], (...mods) => mods);
|
||||
// We need to be self-accepting, AND
|
||||
// we need an explicity array of deps to track changes for SSR-only components
|
||||
SUFFIX += `\nif (import.meta.hot) {
|
||||
import.meta.hot.accept(mod => mod);
|
||||
}`;
|
||||
|
||||
let i = 0;
|
||||
while(i < transformResult.scripts.length) {
|
||||
deps.add(`${id}?astro&type=script&index=${i}`);
|
||||
SUFFIX += `import "${id}?astro&type=script&index=${i}";`;
|
||||
i++;
|
||||
}
|
||||
|
||||
// We only need to define deps if there are any
|
||||
if(deps.size > 1) {
|
||||
SUFFIX += `\nif(import.meta.hot) import.meta.hot.accept(["${id}", "${Array.from(deps).join('","')}"], (...mods) => mods);`
|
||||
} else {
|
||||
SUFFIX += `\nif (import.meta.hot) {
|
||||
import.meta.hot.accept(mod => mod);
|
||||
}`;
|
||||
}
|
||||
}
|
||||
// Add handling to inject scripts into each page JS bundle, if needed.
|
||||
if (isPage) {
|
||||
SUFFIX += `\nimport "${PAGE_SSR_SCRIPT_ID}";`;
|
||||
}
|
||||
|
||||
return {
|
||||
code: `${code}${SUFFIX}`,
|
||||
map,
|
||||
|
@ -260,7 +277,7 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu
|
|||
},
|
||||
async handleHotUpdate(context) {
|
||||
if (context.server.config.isProduction) return;
|
||||
return handleHotUpdate(context, config, logging);
|
||||
return handleHotUpdate.call(this, context, config, logging);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -34,11 +34,12 @@ describe('Imported markdown CSS', function () {
|
|||
});
|
||||
describe('dev', () => {
|
||||
let devServer;
|
||||
let html;
|
||||
let $;
|
||||
|
||||
before(async () => {
|
||||
devServer = await fixture.startDevServer();
|
||||
const html = await fixture.fetch('/').then((res) => res.text());
|
||||
html = await fixture.fetch('/').then((res) => res.text());
|
||||
$ = cheerio.load(html);
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue