summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/popular-horses-lie.md5
-rw-r--r--packages/astro/src/@types/astro.ts1
-rw-r--r--packages/astro/src/core/render/result.ts1
-rw-r--r--packages/astro/src/runtime/server/render/head.ts5
-rw-r--r--packages/astro/test/fixtures/lazy-layout/package.json6
-rw-r--r--packages/astro/test/fixtures/lazy-layout/src/layouts/Main.astro13
-rw-r--r--packages/astro/test/fixtures/lazy-layout/src/pages/index.astro6
-rw-r--r--packages/astro/test/lazy-layout.test.js19
-rw-r--r--pnpm-lock.yaml6
9 files changed, 59 insertions, 3 deletions
diff --git a/.changeset/popular-horses-lie.md b/.changeset/popular-horses-lie.md
new file mode 100644
index 000000000..6d9ffdbbd
--- /dev/null
+++ b/.changeset/popular-horses-lie.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Prevent multiple rendering of head content
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index 6a392f840..c423a1abf 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -1212,6 +1212,7 @@ export interface SSRMetadata {
pathname: string;
hasHydrationScript: boolean;
hasDirectives: Set<string>;
+ hasRenderedHead: boolean;
}
export interface SSRResult {
diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts
index 9eb618cb3..d4704ca1f 100644
--- a/packages/astro/src/core/render/result.ts
+++ b/packages/astro/src/core/render/result.ts
@@ -270,6 +270,7 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site);
renderers,
pathname,
hasHydrationScript: false,
+ hasRenderedHead: false,
hasDirectives: new Set(),
},
response,
diff --git a/packages/astro/src/runtime/server/render/head.ts b/packages/astro/src/runtime/server/render/head.ts
index ed4b73f3e..9afed33fe 100644
--- a/packages/astro/src/runtime/server/render/head.ts
+++ b/packages/astro/src/runtime/server/render/head.ts
@@ -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);
diff --git a/packages/astro/test/fixtures/lazy-layout/package.json b/packages/astro/test/fixtures/lazy-layout/package.json
new file mode 100644
index 000000000..4fe627073
--- /dev/null
+++ b/packages/astro/test/fixtures/lazy-layout/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "@test/lazy-layout",
+ "dependencies": {
+ "astro": "workspace:*"
+ }
+}
diff --git a/packages/astro/test/fixtures/lazy-layout/src/layouts/Main.astro b/packages/astro/test/fixtures/lazy-layout/src/layouts/Main.astro
new file mode 100644
index 000000000..d19faadcb
--- /dev/null
+++ b/packages/astro/test/fixtures/lazy-layout/src/layouts/Main.astro
@@ -0,0 +1,13 @@
+<html>
+ <head>
+ <title>Testing</title>
+ <style>
+ body {
+ background: green;
+ }
+ </style>
+ </head>
+ <body>
+ <slot />
+ </body>
+</html>
diff --git a/packages/astro/test/fixtures/lazy-layout/src/pages/index.astro b/packages/astro/test/fixtures/lazy-layout/src/pages/index.astro
new file mode 100644
index 000000000..603057e53
--- /dev/null
+++ b/packages/astro/test/fixtures/lazy-layout/src/pages/index.astro
@@ -0,0 +1,6 @@
+---
+const Layout = (await import('../layouts/Main.astro')).default;
+---
+<Layout>
+ <div>Stuff here</div>
+</Layout>
diff --git a/packages/astro/test/lazy-layout.test.js b/packages/astro/test/lazy-layout.test.js
new file mode 100644
index 000000000..4ed22f5a0
--- /dev/null
+++ b/packages/astro/test/lazy-layout.test.js
@@ -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);
+ });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bb386d8d9..e12b7f63b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -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:*