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 @@ + + + Test + + +

+ + + 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