Prevent style removal of client:only components (#8472)

This commit is contained in:
Matthew Phillips 2023-09-11 20:39:22 +08:00 committed by GitHub
parent 1ed21d10db
commit fa77fa63d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 0 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Prevent client:only styles from being removed in dev (View Transitions)

View file

@ -113,6 +113,11 @@ const { fallback = 'animate' } = Astro.props as Props;
const parser = new DOMParser(); const parser = new DOMParser();
// A noop element used to prevent styles from being removed
if(import.meta.env.DEV) {
var noopEl: string | undefined = document.createElement('div');
}
async function updateDOM(doc: Document, loc: URL, state?: State, fallback?: Fallback) { async function updateDOM(doc: Document, loc: URL, state?: State, fallback?: Fallback) {
// Check for a head element that should persist, either because it has the data // Check for a head element that should persist, either because it has the data
// attribute or is a link el. // attribute or is a link el.
@ -139,6 +144,16 @@ const { fallback = 'animate' } = Astro.props as Props;
} }
} }
} }
// Only run this in dev. This will get stripped from production builds and is not needed.
if(import.meta.env.DEV) {
if(el.tagName === 'STYLE' && el.dataset.viteDevId) {
const devId = el.dataset.viteDevId;
// If this same style tag exists, remove it from the new page
return doc.querySelector(`style[data-astro-dev-id="${devId}"]`)
// Otherwise, keep it anyways. This is client:only styles.
|| noopEl;
}
}
return null; return null;
}; };

View file

@ -0,0 +1,10 @@
---
import Layout from '../components/Layout.astro';
import Island from '../components/Island';
---
<Layout>
<a id="click-two" href="/client-only-two">go to page 2</a>
<div transition:persist="island">
<Island client:only count={5}>message here</Island>
</div>
</Layout>

View file

@ -0,0 +1,10 @@
---
import Layout from '../components/Layout.astro';
import Island from '../components/Island';
---
<Layout>
<p id="page-two">Page 2</p>
<div transition:persist="island">
<Island client:only count={5}>message here</Island>
</div>
</Layout>

View file

@ -565,4 +565,24 @@ test.describe('View Transitions', () => {
p = page.locator('#one'); p = page.locator('#one');
await expect(p, 'should have content').toHaveText('Page 1'); await expect(p, 'should have content').toHaveText('Page 1');
}); });
test("client:only styles are retained on transition", async ({ page, astro }) => {
const totalExpectedStyles = 8;
// Go to page 1
await page.goto(astro.resolveUrl('/client-only-one'));
let msg = page.locator('.counter-message');
await expect(msg).toHaveText('message here');
let styles = await page.locator('style').all();
expect(styles.length).toEqual(totalExpectedStyles);
await page.click('#click-two');
let pageTwo = page.locator('#page-two');
await expect(pageTwo, 'should have content').toHaveText('Page 2');
styles = await page.locator('style').all();
expect(styles.length).toEqual(totalExpectedStyles, 'style count has not changed');
});
}); });