Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/jolly-loops-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes an issue with the client router where Vue's `:deep()` notation was ignored in dev mode.
13 changes: 13 additions & 0 deletions packages/astro/e2e/view-transitions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1821,4 +1821,17 @@ test.describe('View Transitions', () => {
await expect(page.locator('#style')).toHaveCount(1);
await expect(page.locator('#preload')).toHaveCount(1);
});

test('Styles with data-vite-dev-id persist through head swap', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/island-vue-one'));
let cnt = page.locator('.counter pre');
await expect(cnt).toHaveText('AA0');
await page.locator('[data-vite-dev-id*="VueCounter.vue?vue&type=style"]').evaluate((el) => (el.dataset.marker='this'), undefined);
await page.click('#click-two');
const p = page.locator('#island-two');
await expect(p).toBeVisible();
cnt = page.locator('.counter pre');
await expect(cnt).toHaveText('BB0');
await expect(page.locator('[data-vite-dev-id*="VueCounter.vue?vue&type=style"][data-marker="this"]')).toHaveCount(1);
});
});
10 changes: 10 additions & 0 deletions packages/astro/src/transitions/swap-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,16 @@ const persistedHeadElement = (el: HTMLElement, newDoc: Document): Element | null
const href = el.getAttribute('href');
return newDoc.head.querySelector(`link[rel=stylesheet][href="${href}"]`);
}
// In dev mode, Vite injects <style data-vite-dev-id="..."> elements whose
// textContent is later transformed by HMR (e.g. Vue's `:deep()` → `[data-v-xxx]`).
// Match these by their stable dev ID so the already-transformed style is preserved
// across ClientRouter soft navigations instead of being replaced by the raw version.
if (import.meta.env.DEV && el.tagName === 'STYLE') {
const viteDevId = el.getAttribute('data-vite-dev-id');
Comment thread
martrapp marked this conversation as resolved.
if (viteDevId) {
return newDoc.head.querySelector(`style[data-vite-dev-id="${viteDevId}"]`);
}
}
// Preserve inline <style> elements with identical content across navigations.
// This prevents unnecessary removal and re-insertion of styles (e.g. @font-face
// declarations from <Font>), which would cause the browser to re-evaluate them
Expand Down
Loading