diff options
-rw-r--r-- | .changeset/nasty-gifts-push.md | 5 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/invalidate-script-deps/package.json | 8 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/invalidate-script-deps/src/pages/index.astro | 11 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/invalidate-script-deps/src/scripts/heading.js | 2 | ||||
-rw-r--r-- | packages/astro/e2e/invalidate-script-deps.test.js | 31 | ||||
-rw-r--r-- | packages/astro/src/vite-plugin-astro/hmr.ts | 14 | ||||
-rw-r--r-- | packages/astro/src/vite-plugin-astro/index.ts | 6 | ||||
-rw-r--r-- | packages/astro/src/vite-plugin-astro/query.ts | 5 | ||||
-rw-r--r-- | pnpm-lock.yaml | 6 |
9 files changed, 86 insertions, 2 deletions
diff --git a/.changeset/nasty-gifts-push.md b/.changeset/nasty-gifts-push.md new file mode 100644 index 000000000..8c175ef77 --- /dev/null +++ b/.changeset/nasty-gifts-push.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Properly invalidate Astro modules when a child script updates in HMR diff --git a/packages/astro/e2e/fixtures/invalidate-script-deps/package.json b/packages/astro/e2e/fixtures/invalidate-script-deps/package.json new file mode 100644 index 000000000..4b45ad505 --- /dev/null +++ b/packages/astro/e2e/fixtures/invalidate-script-deps/package.json @@ -0,0 +1,8 @@ +{ + "name": "@e2e/invalidate-script-deps", + "version": "0.0.0", + "private": true, + "devDependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/e2e/fixtures/invalidate-script-deps/src/pages/index.astro b/packages/astro/e2e/fixtures/invalidate-script-deps/src/pages/index.astro new file mode 100644 index 000000000..3954329f4 --- /dev/null +++ b/packages/astro/e2e/fixtures/invalidate-script-deps/src/pages/index.astro @@ -0,0 +1,11 @@ +<html> + <head> + <title>Test</title> + </head> + <body> + <h1></h1> + <script> + import '../scripts/heading.js'; + </script> + </body> +</html> diff --git a/packages/astro/e2e/fixtures/invalidate-script-deps/src/scripts/heading.js b/packages/astro/e2e/fixtures/invalidate-script-deps/src/scripts/heading.js new file mode 100644 index 000000000..0d3fece4a --- /dev/null +++ b/packages/astro/e2e/fixtures/invalidate-script-deps/src/scripts/heading.js @@ -0,0 +1,2 @@ + +document.querySelector('h1').textContent = 'before'; diff --git a/packages/astro/e2e/invalidate-script-deps.test.js b/packages/astro/e2e/invalidate-script-deps.test.js new file mode 100644 index 000000000..811f6bdfd --- /dev/null +++ b/packages/astro/e2e/invalidate-script-deps.test.js @@ -0,0 +1,31 @@ +import { expect } from '@playwright/test'; +import { testFactory } from './test-utils.js'; + +const test = testFactory({ + root: './fixtures/invalidate-script-deps/', +}); + +let devServer; + +test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterEach(async () => { + await devServer.stop(); +}); + +test.describe('Scripts with dependencies', () => { + test('refresh with HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const h = page.locator('h1'); + await expect(h, 'original text set').toHaveText('before'); + + await astro.editFile('./src/scripts/heading.js', (original) => + original.replace('before', 'after') + ); + + await expect(h, 'text changed').toHaveText('after'); + }); +}); diff --git a/packages/astro/src/vite-plugin-astro/hmr.ts b/packages/astro/src/vite-plugin-astro/hmr.ts index f44b844f7..e307166db 100644 --- a/packages/astro/src/vite-plugin-astro/hmr.ts +++ b/packages/astro/src/vite-plugin-astro/hmr.ts @@ -6,6 +6,7 @@ import type { LogOptions } from '../core/logger/core.js'; import { info } from '../core/logger/core.js'; import * as msg from '../core/messages.js'; import { cachedCompilation, invalidateCompilation, isCached } from './compile.js'; +import { isAstroScript } from './query.js'; interface TrackCSSDependenciesOptions { viteDevServer: ViteDevServer | null; @@ -141,12 +142,23 @@ export async function handleHotUpdate( // 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')) { + if (imp.id && isAstroScript(imp.id)) { mods.push(imp); } } } + // If this is a module that is imported from a <script>, invalidate the Astro + // component so that it is cached by the time the script gets transformed. + for(const mod of filtered) { + if(mod.id && isAstroScript(mod.id) && mod.file) { + const astroMod = ctx.server.moduleGraph.getModuleById(mod.file); + if(astroMod) { + mods.unshift(astroMod); + } + } + } + // TODO: Svelte files should be marked as `isSelfAccepting` but they don't appear to be const isSelfAccepting = mods.every((m) => m.isSelfAccepting || m.url.endsWith('.svelte')); if (isSelfAccepting) { diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts index 8d59d6fa7..2e5eb54ff 100644 --- a/packages/astro/src/vite-plugin-astro/index.ts +++ b/packages/astro/src/vite-plugin-astro/index.ts @@ -359,7 +359,11 @@ ${source} pluginContext: this, }; const compile = () => cachedCompilation(compileProps); - return handleHotUpdate.call(this, context, { config, logging, compile }); + return handleHotUpdate.call(this, context, { + config, + logging, + compile + }); }, }; } diff --git a/packages/astro/src/vite-plugin-astro/query.ts b/packages/astro/src/vite-plugin-astro/query.ts index bc4908bbe..1d3f13f82 100644 --- a/packages/astro/src/vite-plugin-astro/query.ts +++ b/packages/astro/src/vite-plugin-astro/query.ts @@ -35,3 +35,8 @@ export function parseAstroRequest(id: string): ParsedRequestResult { query, }; } + +export function isAstroScript(id: string): boolean { + const parsed = parseAstroRequest(id); + return parsed.query.type === 'script'; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 870be2829..265f3716e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -659,6 +659,12 @@ importers: react: 18.2.0 react-dom: 18.2.0_react@18.2.0 + packages/astro/e2e/fixtures/invalidate-script-deps: + specifiers: + astro: workspace:* + devDependencies: + astro: link:../../.. + packages/astro/e2e/fixtures/lit-component: specifiers: '@astrojs/lit': workspace:* |