summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Bjorn Lu <bjornlu.dev@gmail.com> 2023-09-29 21:55:46 +0800
committerGravatar GitHub <noreply@github.com> 2023-09-29 21:55:46 +0800
commit345808170fce783ddd3c9a4035a91fa64dcc5f46 (patch)
tree55d68006430a02dc4ab11ea3ea20f761c9423f24
parent31c59ad8b6a72f95c98a306ecf92d198c03110b4 (diff)
downloadastro-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.md5
-rw-r--r--packages/astro/e2e/css-sourcemaps.test.js36
-rw-r--r--packages/astro/e2e/css.test.js18
-rw-r--r--packages/astro/e2e/fixtures/css-sourcemaps/astro.config.mjs7
-rw-r--r--packages/astro/e2e/fixtures/css-sourcemaps/package.json8
-rw-r--r--packages/astro/e2e/fixtures/css-sourcemaps/src/env.d.ts1
-rw-r--r--packages/astro/e2e/fixtures/css-sourcemaps/src/pages/index.astro9
-rw-r--r--packages/astro/e2e/fixtures/css-sourcemaps/src/styles/main.css3
-rw-r--r--packages/astro/e2e/view-transitions.test.js2
-rw-r--r--packages/astro/src/runtime/client/hmr.ts45
-rw-r--r--packages/astro/src/transitions/router.ts2
-rw-r--r--packages/astro/src/vite-plugin-astro-server/css.ts2
-rw-r--r--packages/astro/src/vite-plugin-astro-server/route.ts15
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,
});