diff --git a/.changeset/breezy-toys-hear.md b/.changeset/breezy-toys-hear.md new file mode 100644 index 000000000000..d49d4eede560 --- /dev/null +++ b/.changeset/breezy-toys-hear.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes stale scoped styles during HMR when both markup and `'; + const newCode = '
new
\n'; + + const astroFileToCompileMetadata = new Map(); + astroFileToCompileMetadata.set(file, { + originalCode: oldCode, + css: [{ code: '.t { --gen: 0; }' }], + scripts: [], + }); + + const ctx = createHmrTestContext({ file, newCode }); + + const result = await handleHotUpdate(ctx as any, { + logger: defaultLogger, + compile: async () => ({}) as any, + astroFileToCompileMetadata, + }); + + // Returns undefined so Vite uses its default full-module invalidation + assert.equal(result, undefined); + // The stale metadata entry must be deleted so the load hook recompiles from disk + assert.equal(astroFileToCompileMetadata.has(file), false); + }); + + it('keeps metadata and eagerly recompiles when only style changes', async () => { + const file = '/src/components/Target.astro'; + const oldCode = '
same
\n'; + const newCode = '
same
\n'; + + const astroFileToCompileMetadata = new Map(); + astroFileToCompileMetadata.set(file, { + originalCode: oldCode, + css: [{ code: '.t { --gen: 0; }' }], + scripts: [], + }); + + const styleModule = { id: file + '?astro&type=style&index=0&lang.css' }; + const ctx = createHmrTestContext({ file, newCode, modules: [styleModule] }); + const compile = async (code: string, filename: string) => { + astroFileToCompileMetadata.set(filename, { + originalCode: code, + css: [{ code: '.t { --gen: 1; }' }], + scripts: [], + }); + return {}; + }; + + const result = await handleHotUpdate(ctx as any, { + logger: defaultLogger, + compile: compile as any, + astroFileToCompileMetadata, + }); + + // Returns the style modules for targeted CSS HMR + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0], styleModule); + assert.deepEqual(astroFileToCompileMetadata.get(file), { + originalCode: newCode, + css: [{ code: '.t { --gen: 1; }' }], + scripts: [], + }); + }); + + it('deletes compile metadata when only frontmatter changes', async () => { + const file = '/src/components/Target.astro'; + const oldCode = '---\nconst x = 1;\n---\n
same
\n'; + const newCode = '---\nconst x = 2;\n---\n
same
\n'; + + const astroFileToCompileMetadata = new Map(); + astroFileToCompileMetadata.set(file, { + originalCode: oldCode, + css: [{ code: '.t { color: red; }' }], + scripts: [], + }); + + const ctx = createHmrTestContext({ file, newCode }); + + await handleHotUpdate(ctx as any, { + logger: defaultLogger, + compile: async () => ({}) as any, + astroFileToCompileMetadata, + }); + + assert.equal(astroFileToCompileMetadata.has(file), false); + }); +}); describe('isStyleOnlyChanged', () => { it('should return false if nothing change', () => {