From ccea6a0a1ae55ab057d94f60014e2183013b5f60 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Wed, 11 May 2022 09:23:11 -0600 Subject: [PATCH] HMR hoisted scripts (#3336) * HMR hoisted scripts * Add to the dep graph * Remove example change * Adds changeset * Fix markdown test --- .changeset/happy-wasps-check.md | 5 +++ examples/minimal/src/pages/index.astro | 2 +- packages/astro/src/vite-plugin-astro/hmr.ts | 10 ++++++ packages/astro/src/vite-plugin-astro/index.ts | 31 ++++++++++++++----- .../astro/test/astro-markdown-css.test.js | 3 +- 5 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 .changeset/happy-wasps-check.md diff --git a/.changeset/happy-wasps-check.md b/.changeset/happy-wasps-check.md new file mode 100644 index 000000000..6fb90627b --- /dev/null +++ b/.changeset/happy-wasps-check.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes HMR of hoisted script tags diff --git a/examples/minimal/src/pages/index.astro b/examples/minimal/src/pages/index.astro index 25f796bf1..346e155c4 100644 --- a/examples/minimal/src/pages/index.astro +++ b/examples/minimal/src/pages/index.astro @@ -10,4 +10,4 @@

Astro

- \ No newline at end of file + diff --git a/packages/astro/src/vite-plugin-astro/hmr.ts b/packages/astro/src/vite-plugin-astro/hmr.ts index 4e194993e..2b11585ca 100644 --- a/packages/astro/src/vite-plugin-astro/hmr.ts +++ b/packages/astro/src/vite-plugin-astro/hmr.ts @@ -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, '/'); diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts index ea6f17dcd..47ecfee1e 100644 --- a/packages/astro/src/vite-plugin-astro/index.ts +++ b/packages/astro/src/vite-plugin-astro/index.ts @@ -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); }, }; } diff --git a/packages/astro/test/astro-markdown-css.test.js b/packages/astro/test/astro-markdown-css.test.js index 40710ce85..fcb1408f0 100644 --- a/packages/astro/test/astro-markdown-css.test.js +++ b/packages/astro/test/astro-markdown-css.test.js @@ -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); });