diff options
author | 2023-09-29 21:55:46 +0800 | |
---|---|---|
committer | 2023-09-29 21:55:46 +0800 | |
commit | 345808170fce783ddd3c9a4035a91fa64dcc5f46 (patch) | |
tree | 55d68006430a02dc4ab11ea3ea20f761c9423f24 | |
parent | 31c59ad8b6a72f95c98a306ecf92d198c03110b4 (diff) | |
download | astro-345808170fce783ddd3c9a4035a91fa64dcc5f46.tar.gz astro-345808170fce783ddd3c9a4035a91fa64dcc5f46.tar.zst astro-345808170fce783ddd3c9a4035a91fa64dcc5f46.zip |
Fix duplicated Astro and Vite injected styles (#8706)
-rw-r--r-- | .changeset/olive-bags-think.md | 5 | ||||
-rw-r--r-- | packages/astro/e2e/css-sourcemaps.test.js | 36 | ||||
-rw-r--r-- | packages/astro/e2e/css.test.js | 18 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/css-sourcemaps/astro.config.mjs | 7 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/css-sourcemaps/package.json | 8 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/css-sourcemaps/src/env.d.ts | 1 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/css-sourcemaps/src/pages/index.astro | 9 | ||||
-rw-r--r-- | packages/astro/e2e/fixtures/css-sourcemaps/src/styles/main.css | 3 | ||||
-rw-r--r-- | packages/astro/e2e/view-transitions.test.js | 2 | ||||
-rw-r--r-- | packages/astro/src/runtime/client/hmr.ts | 45 | ||||
-rw-r--r-- | packages/astro/src/transitions/router.ts | 2 | ||||
-rw-r--r-- | packages/astro/src/vite-plugin-astro-server/css.ts | 2 | ||||
-rw-r--r-- | packages/astro/src/vite-plugin-astro-server/route.ts | 15 |
13 files changed, 18 insertions, 135 deletions
diff --git a/.changeset/olive-bags-think.md b/.changeset/olive-bags-think.md new file mode 100644 index 000000000..70fc7501e --- /dev/null +++ b/.changeset/olive-bags-think.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix duplicated Astro and Vite injected styles diff --git a/packages/astro/e2e/css-sourcemaps.test.js b/packages/astro/e2e/css-sourcemaps.test.js deleted file mode 100644 index 4ea3fc0e2..000000000 --- a/packages/astro/e2e/css-sourcemaps.test.js +++ /dev/null @@ -1,36 +0,0 @@ -import { expect } from '@playwright/test'; -import { testFactory } from './test-utils.js'; - -const test = testFactory({ - root: './fixtures/css/', -}); - -let devServer; - -test.beforeAll(async ({ astro }) => { - devServer = await astro.startDevServer(); -}); - -test.afterAll(async () => { - await devServer.stop(); -}); - -test.describe('CSS Sourcemap HMR', () => { - test('removes Astro-injected CSS once Vite-injected CSS loads', async ({ page, astro }) => { - const html = await astro.fetch('/').then((res) => res.text()); - - // style[data-astro-dev-id] should exist in initial SSR'd markup - expect(html).toMatch('data-astro-dev-id'); - - await page.goto(astro.resolveUrl('/')); - - // Ensure JS has initialized - await page.waitForTimeout(500); - - // style[data-astro-dev-id] should NOT exist once JS runs - expect(await page.locator('style[data-astro-dev-id]').count()).toEqual(0); - - // style[data-vite-dev-id] should exist now - expect(await page.locator('style[data-vite-dev-id]').count()).toBeGreaterThan(0); - }); -}); diff --git a/packages/astro/e2e/css.test.js b/packages/astro/e2e/css.test.js index b302d9d90..3e0486d0f 100644 --- a/packages/astro/e2e/css.test.js +++ b/packages/astro/e2e/css.test.js @@ -29,21 +29,9 @@ test.describe('CSS HMR', () => { await expect(h).toHaveCSS('color', 'rgb(0, 128, 0)'); }); - test('removes Astro-injected CSS once Vite-injected CSS loads', async ({ page, astro }) => { + test('removes Astro-injected CSS once Vite-injected CSS loads', async ({ astro }) => { const html = await astro.fetch('/').then((res) => res.text()); - - // style[data-astro-dev-id] should exist in initial SSR'd markup - expect(html).toMatch('data-astro-dev-id'); - - await page.goto(astro.resolveUrl('/')); - - // Ensure JS has initialized - await page.waitForTimeout(500); - - // style[data-astro-dev-id] should NOT exist once JS runs - expect(await page.locator('style[data-astro-dev-id]').count()).toEqual(0); - - // style[data-vite-dev-id] should exist now - expect(await page.locator('style[data-vite-dev-id]').count()).toBeGreaterThan(0); + // style[data-vite-dev-id] should exist in initial SSR'd markup + expect(html).toMatch('data-vite-dev-id'); }); }); diff --git a/packages/astro/e2e/fixtures/css-sourcemaps/astro.config.mjs b/packages/astro/e2e/fixtures/css-sourcemaps/astro.config.mjs deleted file mode 100644 index 7e8fac1e7..000000000 --- a/packages/astro/e2e/fixtures/css-sourcemaps/astro.config.mjs +++ /dev/null @@ -1,7 +0,0 @@ -export default { - vite: { - css: { - devSourcemap: true, - } - } -}; diff --git a/packages/astro/e2e/fixtures/css-sourcemaps/package.json b/packages/astro/e2e/fixtures/css-sourcemaps/package.json deleted file mode 100644 index 1fa4c2c79..000000000 --- a/packages/astro/e2e/fixtures/css-sourcemaps/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@e2e/css-sourcemaps", - "version": "0.0.0", - "private": true, - "dependencies": { - "astro": "workspace:*" - } -} diff --git a/packages/astro/e2e/fixtures/css-sourcemaps/src/env.d.ts b/packages/astro/e2e/fixtures/css-sourcemaps/src/env.d.ts deleted file mode 100644 index 8c34fb45e..000000000 --- a/packages/astro/e2e/fixtures/css-sourcemaps/src/env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// <reference types="astro/client" />
\ No newline at end of file diff --git a/packages/astro/e2e/fixtures/css-sourcemaps/src/pages/index.astro b/packages/astro/e2e/fixtures/css-sourcemaps/src/pages/index.astro deleted file mode 100644 index 7275177f9..000000000 --- a/packages/astro/e2e/fixtures/css-sourcemaps/src/pages/index.astro +++ /dev/null @@ -1,9 +0,0 @@ -<h1>hello world</h1> - -<style> - @import "../styles/main.css"; - - h1 { - color: var(--h1-color); - } -</style> diff --git a/packages/astro/e2e/fixtures/css-sourcemaps/src/styles/main.css b/packages/astro/e2e/fixtures/css-sourcemaps/src/styles/main.css deleted file mode 100644 index c80a6cde1..000000000 --- a/packages/astro/e2e/fixtures/css-sourcemaps/src/styles/main.css +++ /dev/null @@ -1,3 +0,0 @@ -:root { - --h1-color: red; -} diff --git a/packages/astro/e2e/view-transitions.test.js b/packages/astro/e2e/view-transitions.test.js index 05a8f8ad0..a04b905af 100644 --- a/packages/astro/e2e/view-transitions.test.js +++ b/packages/astro/e2e/view-transitions.test.js @@ -631,7 +631,7 @@ test.describe('View Transitions', () => { }); test('client:only styles are retained on transition', async ({ page, astro }) => { - const totalExpectedStyles = 8; + const totalExpectedStyles = 7; // Go to page 1 await page.goto(astro.resolveUrl('/client-only-one')); diff --git a/packages/astro/src/runtime/client/hmr.ts b/packages/astro/src/runtime/client/hmr.ts index 989ddc6b9..5b6eddc23 100644 --- a/packages/astro/src/runtime/client/hmr.ts +++ b/packages/astro/src/runtime/client/hmr.ts @@ -1,46 +1,7 @@ /// <reference types="vite/client" /> if (import.meta.hot) { - // Vite injects `<style data-vite-dev-id>` for ESM imports of styles - // but Astro also SSRs with `<style data-astro-dev-id>` blocks. This MutationObserver - // removes any duplicates as soon as they are hydrated client-side. - const injectedStyles = getInjectedStyles(); - const mo = new MutationObserver((records) => { - for (const record of records) { - for (const node of record.addedNodes) { - if (isViteInjectedStyle(node)) { - injectedStyles.get(node.getAttribute('data-vite-dev-id')!)?.remove(); - } - } - } - }); - mo.observe(document.documentElement, { subtree: true, childList: true }); - - // Vue `link` styles need to be manually refreshed in Firefox - import.meta.hot.on('vite:beforeUpdate', async (payload) => { - for (const file of payload.updates) { - if (file.acceptedPath.includes('vue&type=style')) { - const link = document.querySelector(`link[href="${file.acceptedPath}"]`); - if (link) { - link.replaceWith(link.cloneNode(true)); - } - } - } - }); -} - -function getInjectedStyles() { - const injectedStyles = new Map<string, Element>(); - document.querySelectorAll<HTMLStyleElement>('style[data-astro-dev-id]').forEach((el) => { - injectedStyles.set(el.getAttribute('data-astro-dev-id')!, el); - }); - return injectedStyles; -} - -function isStyle(node: Node): node is HTMLStyleElement { - return node.nodeType === node.ELEMENT_NODE && (node as Element).tagName.toLowerCase() === 'style'; -} - -function isViteInjectedStyle(node: Node): node is HTMLStyleElement { - return isStyle(node) && !!node.getAttribute('data-vite-dev-id'); + // HMR temporarily not needed for now, but kept here in case we need it again. + // To re-instate this module again, update `vite-plugin-astro-server/route.ts` + // to add this module as a script similar to `/@vite/client` } diff --git a/packages/astro/src/transitions/router.ts b/packages/astro/src/transitions/router.ts index aabba6429..12ac5615d 100644 --- a/packages/astro/src/transitions/router.ts +++ b/packages/astro/src/transitions/router.ts @@ -208,7 +208,7 @@ async function updateDOM( const devId = el.dataset.viteDevId; // If this same style tag exists, remove it from the new page return ( - newDocument.querySelector(`style[data-astro-dev-id="${devId}"]`) || + newDocument.querySelector(`style[data-vite-dev-id="${devId}"]`) || // Otherwise, keep it anyways. This is client:only styles. noopEl ); diff --git a/packages/astro/src/vite-plugin-astro-server/css.ts b/packages/astro/src/vite-plugin-astro-server/css.ts index 46f1235bb..d256f48c7 100644 --- a/packages/astro/src/vite-plugin-astro-server/css.ts +++ b/packages/astro/src/vite-plugin-astro-server/css.ts @@ -28,7 +28,7 @@ export async function getStylesForURL( mode === 'development' && // only inline in development typeof ssrModule?.default === 'string' // ignore JS module styles ) { - importedStylesMap.set(importedModule.url, ssrModule.default); + importedStylesMap.set(importedModule.id ?? importedModule.url, ssrModule.default); } else { // NOTE: We use the `url` property here. `id` would break Windows. importedCssUrls.add(importedModule.url); diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts index a567c3266..34ab119da 100644 --- a/packages/astro/src/vite-plugin-astro-server/route.ts +++ b/packages/astro/src/vite-plugin-astro-server/route.ts @@ -12,7 +12,7 @@ import { loadMiddleware } from '../core/middleware/loadMiddleware.js'; import { createRenderContext, getParamsAndProps, type SSROptions } from '../core/render/index.js'; import { createRequest } from '../core/request.js'; import { matchAllRoutes } from '../core/routing/index.js'; -import { isPage, resolveIdToUrl, viteID } from '../core/util.js'; +import { isPage } from '../core/util.js'; import { getSortedPreloadedMatches } from '../prerender/routing.js'; import { isServerLikeOutput } from '../prerender/utils.js'; import { PAGE_SCRIPT_ID } from '../vite-plugin-scripts/index.js'; @@ -275,13 +275,6 @@ async function getScriptsAndStyles({ pipeline, filePath }: GetScriptsAndStylesPa props: { type: 'module', src: '/@vite/client' }, children: '', }); - scripts.add({ - props: { - type: 'module', - src: await resolveIdToUrl(moduleLoader, 'astro/runtime/client/hmr.js'), - }, - children: '', - }); } // TODO: We should allow adding generic HTML elements to the head, not just scripts @@ -322,11 +315,11 @@ async function getScriptsAndStyles({ pipeline, filePath }: GetScriptsAndStylesPa }, children: '', }); - // But we still want to inject the styles to avoid FOUC + // But we still want to inject the styles to avoid FOUC. The style tags + // should emulate what Vite injects so further HMR works as expected. styles.add({ props: { - // Track the ID so we can match it to Vite's injected style later - 'data-astro-dev-id': viteID(new URL(`.${url}`, settings.config.root)), + 'data-vite-dev-id': url, }, children: content, }); |