diff --git a/.changeset/hungry-phones-melt.md b/.changeset/hungry-phones-melt.md
new file mode 100644
index 0000000000..eb01a31f53
--- /dev/null
+++ b/.changeset/hungry-phones-melt.md
@@ -0,0 +1,5 @@
+---
+"astro": patch
+---
+
+Fixes regression when handling hoisted scripts from content collections
diff --git a/packages/astro/src/core/build/plugins/plugin-analyzer.ts b/packages/astro/src/core/build/plugins/plugin-analyzer.ts
index e91820fb93..83d8b9cdc3 100644
--- a/packages/astro/src/core/build/plugins/plugin-analyzer.ts
+++ b/packages/astro/src/core/build/plugins/plugin-analyzer.ts
@@ -54,7 +54,12 @@ export function vitePluginAnalyzer(
if (hoistedScripts.size) {
for (const parentInfo of getParentModuleInfos(from, this, isPropagatedAsset)) {
if (isPropagatedAsset(parentInfo.id)) {
- internals.propagatedScriptsMap.set(parentInfo.id, hoistedScripts);
+ for (const hid of hoistedScripts) {
+ if (!internals.propagatedScriptsMap.has(parentInfo.id)) {
+ internals.propagatedScriptsMap.set(parentInfo.id, new Set());
+ }
+ internals.propagatedScriptsMap.get(parentInfo.id)?.add(hid);
+ }
} else if (moduleIsTopLevelPage(parentInfo)) {
for (const hid of hoistedScripts) {
if (!pageScripts.has(parentInfo.id)) {
diff --git a/packages/astro/test/content-collections.test.js b/packages/astro/test/content-collections.test.js
index 29ad26a2f1..b7f5abb07c 100644
--- a/packages/astro/test/content-collections.test.js
+++ b/packages/astro/test/content-collections.test.js
@@ -145,6 +145,25 @@ describe('Content Collections', () => {
});
});
});
+
+ describe('Hoisted scripts', () => {
+ it('Contains all the scripts imported by components', async () => {
+ const html = await fixture.readFile('/with-scripts/one/index.html');
+ const $ = cheerio.load(html);
+ // NOTE: Hoisted scripts have two tags currently but could be optimized as one. However, we're moving towards
+ // `experimental.directRenderScript` so this optimization isn't a priority at the moment.
+ assert.equal($('script').length, 2);
+ // Read the scripts' content
+ const scripts = $('script')
+ .map((_, el) => $(el).attr('src'))
+ .toArray();
+ const scriptsCode = (
+ await Promise.all(scripts.map(async (src) => await fixture.readFile(src)))
+ ).join('\n');
+ assert.match(scriptsCode, /ScriptCompA/);
+ assert.match(scriptsCode, /ScriptCompB/);
+ });
+ });
});
const blogSlugToContents = {
diff --git a/packages/astro/test/fixtures/content-collections/src/components/ScriptCompA.astro b/packages/astro/test/fixtures/content-collections/src/components/ScriptCompA.astro
new file mode 100644
index 0000000000..8b1e7dff16
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections/src/components/ScriptCompA.astro
@@ -0,0 +1 @@
+
diff --git a/packages/astro/test/fixtures/content-collections/src/components/ScriptCompB.astro b/packages/astro/test/fixtures/content-collections/src/components/ScriptCompB.astro
new file mode 100644
index 0000000000..e133a2f518
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections/src/components/ScriptCompB.astro
@@ -0,0 +1 @@
+
diff --git a/packages/astro/test/fixtures/content-collections/src/content/with-scripts/one.mdx b/packages/astro/test/fixtures/content-collections/src/content/with-scripts/one.mdx
new file mode 100644
index 0000000000..049a25a377
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections/src/content/with-scripts/one.mdx
@@ -0,0 +1,7 @@
+import ScriptCompA from '../../components/ScriptCompA.astro'
+import ScriptCompB from '../../components/ScriptCompB.astro'
+
+Both scripts should exist.
+
+
+
diff --git a/packages/astro/test/fixtures/content-collections/src/pages/with-scripts/[...slug].astro b/packages/astro/test/fixtures/content-collections/src/pages/with-scripts/[...slug].astro
new file mode 100644
index 0000000000..893cbb9c61
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections/src/pages/with-scripts/[...slug].astro
@@ -0,0 +1,21 @@
+---
+import { getCollection } from 'astro:content';
+
+export async function getStaticPaths() {
+ const blogEntries = await getCollection('with-scripts');
+ return blogEntries.map(entry => ({
+ params: { slug: entry.slug }, props: { entry },
+ }));
+}
+
+const { entry } = Astro.props;
+
+const { Content } = await entry.render();
+const { title } = entry.data;
+---
+
+
+ This is a content collection post
+ {title}
+
+