Ensure head content rendered once with lazy layouts (#4892)
* Ensure head content rendered once with lazy layouts * Add changeset
This commit is contained in:
parent
649e9080cb
commit
ff7ba0ee0f
9 changed files with 59 additions and 3 deletions
5
.changeset/popular-horses-lie.md
Normal file
5
.changeset/popular-horses-lie.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Prevent multiple rendering of head content
|
|
@ -1212,6 +1212,7 @@ export interface SSRMetadata {
|
|||
pathname: string;
|
||||
hasHydrationScript: boolean;
|
||||
hasDirectives: Set<string>;
|
||||
hasRenderedHead: boolean;
|
||||
}
|
||||
|
||||
export interface SSRResult {
|
||||
|
|
|
@ -270,6 +270,7 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
|||
renderers,
|
||||
pathname,
|
||||
hasHydrationScript: false,
|
||||
hasRenderedHead: false,
|
||||
hasDirectives: new Set(),
|
||||
},
|
||||
response,
|
||||
|
|
|
@ -12,9 +12,8 @@ const uniqueElements = (item: any, index: number, all: any[]) => {
|
|||
);
|
||||
};
|
||||
|
||||
const alreadyHeadRenderedResults = new WeakSet<SSRResult>();
|
||||
export function renderHead(result: SSRResult): Promise<string> {
|
||||
alreadyHeadRenderedResults.add(result);
|
||||
result._metadata.hasRenderedHead = true;
|
||||
const styles = Array.from(result.styles)
|
||||
.filter(uniqueElements)
|
||||
.map((style) => renderElement('style', style));
|
||||
|
@ -36,7 +35,7 @@ export function renderHead(result: SSRResult): Promise<string> {
|
|||
// is called before a component's first non-head HTML element. If the head was
|
||||
// already injected it is a noop.
|
||||
export async function* maybeRenderHead(result: SSRResult): AsyncIterable<string> {
|
||||
if (alreadyHeadRenderedResults.has(result)) {
|
||||
if (result._metadata.hasRenderedHead) {
|
||||
return;
|
||||
}
|
||||
yield renderHead(result);
|
||||
|
|
6
packages/astro/test/fixtures/lazy-layout/package.json
vendored
Normal file
6
packages/astro/test/fixtures/lazy-layout/package.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "@test/lazy-layout",
|
||||
"dependencies": {
|
||||
"astro": "workspace:*"
|
||||
}
|
||||
}
|
13
packages/astro/test/fixtures/lazy-layout/src/layouts/Main.astro
vendored
Normal file
13
packages/astro/test/fixtures/lazy-layout/src/layouts/Main.astro
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Testing</title>
|
||||
<style>
|
||||
body {
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
6
packages/astro/test/fixtures/lazy-layout/src/pages/index.astro
vendored
Normal file
6
packages/astro/test/fixtures/lazy-layout/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
const Layout = (await import('../layouts/Main.astro')).default;
|
||||
---
|
||||
<Layout>
|
||||
<div>Stuff here</div>
|
||||
</Layout>
|
19
packages/astro/test/lazy-layout.test.js
Normal file
19
packages/astro/test/lazy-layout.test.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { expect } from 'chai';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
|
||||
describe('Lazily imported layouts', () => {
|
||||
/** @type {import('./test-utils').Fixture} */
|
||||
let fixture;
|
||||
|
||||
before(async () => {
|
||||
fixture = await loadFixture({ root: './fixtures/lazy-layout/' });
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('Renders styles only once', async () => {
|
||||
const html = await fixture.readFile('/index.html');
|
||||
const $ = cheerio.load(html);
|
||||
expect($('link')).to.have.a.lengthOf(1);
|
||||
});
|
||||
});
|
|
@ -1664,6 +1664,12 @@ importers:
|
|||
'@astrojs/solid-js': link:../../../../integrations/solid
|
||||
astro: link:../../..
|
||||
|
||||
packages/astro/test/fixtures/lazy-layout:
|
||||
specifiers:
|
||||
astro: workspace:*
|
||||
dependencies:
|
||||
astro: link:../../..
|
||||
|
||||
packages/astro/test/fixtures/legacy-astro-flavored-markdown:
|
||||
specifiers:
|
||||
'@astrojs/preact': workspace:*
|
||||
|
|
Loading…
Reference in a new issue