summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/silly-ears-unite.md5
-rw-r--r--packages/astro/src/core/build/internal.ts8
-rw-r--r--packages/astro/src/core/build/static-build.ts23
-rw-r--r--packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts15
4 files changed, 41 insertions, 10 deletions
diff --git a/.changeset/silly-ears-unite.md b/.changeset/silly-ears-unite.md
new file mode 100644
index 000000000..b4e23917b
--- /dev/null
+++ b/.changeset/silly-ears-unite.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fix build issue where hoisted scripts would be duplicated per page
diff --git a/packages/astro/src/core/build/internal.ts b/packages/astro/src/core/build/internal.ts
index c6f98a4fa..e796804fb 100644
--- a/packages/astro/src/core/build/internal.ts
+++ b/packages/astro/src/core/build/internal.ts
@@ -8,8 +8,10 @@ export interface BuildInternals {
// Pure CSS chunks are chunks that only contain CSS.
pureCSSChunks: Set<RenderedChunk>;
- // TODO document what this is
+ // A mapping of hoisted script ids back to the exact hoisted scripts it references
hoistedScriptIdToHoistedMap: Map<string, Set<string>>;
+ // A mapping of hoisted script ids back to the pages which reference it
+ hoistedScriptIdToPagesMap: Map<string, Set<string>>;
// A mapping of specifiers like astro/client/idle.js to the hashed bundled name.
// Used to render pages with the correct specifiers.
@@ -50,9 +52,13 @@ export function createBuildInternals(): BuildInternals {
// These are for tracking hoisted script bundling
const hoistedScriptIdToHoistedMap = new Map<string, Set<string>>();
+ // This tracks hoistedScriptId => page components
+ const hoistedScriptIdToPagesMap = new Map<string, Set<string>>();
+
return {
pureCSSChunks,
hoistedScriptIdToHoistedMap,
+ hoistedScriptIdToPagesMap,
entrySpecifierToBundleMap: new Map<string, string>(),
pagesByComponent: new Map(),
diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts
index ae08c54dc..f101f6a3d 100644
--- a/packages/astro/src/core/build/static-build.ts
+++ b/packages/astro/src/core/build/static-build.ts
@@ -38,6 +38,7 @@ export async function staticBuild(opts: StaticBuildOptions) {
// Build internals needed by the CSS plugin
const internals = createBuildInternals();
+ const uniqueHoistedIds = new Map<string, string>();
const timer: Record<string, number> = {};
@@ -76,9 +77,27 @@ export async function staticBuild(opts: StaticBuildOptions) {
// Add hoisted scripts
const hoistedScripts = new Set(metadata.hoistedScriptPaths());
if (hoistedScripts.size) {
- const moduleId = npath.posix.join(astroModuleId, 'hoisted.js');
- internals.hoistedScriptIdToHoistedMap.set(moduleId, hoistedScripts);
+ const uniqueHoistedId = JSON.stringify(Array.from(hoistedScripts).sort());
+ let moduleId: string;
+
+ // If we're already tracking this set of hoisted scripts, get the unique id
+ if (uniqueHoistedIds.has(uniqueHoistedId)) {
+ moduleId = uniqueHoistedIds.get(uniqueHoistedId)!;
+ } else {
+ // Otherwise, create a unique id for this set of hoisted scripts
+ moduleId = `/astro/hoisted.js?q=${uniqueHoistedIds.size}`;
+ uniqueHoistedIds.set(uniqueHoistedId, moduleId);
+ }
topLevelImports.add(moduleId);
+
+ // Make sure to track that this page uses this set of hoisted scripts
+ if (internals.hoistedScriptIdToPagesMap.has(moduleId)) {
+ const pages = internals.hoistedScriptIdToPagesMap.get(moduleId);
+ pages!.add(astroModuleId);
+ } else {
+ internals.hoistedScriptIdToPagesMap.set(moduleId, new Set([astroModuleId]))
+ internals.hoistedScriptIdToHoistedMap.set(moduleId, hoistedScripts);
+ }
}
for (const specifier of topLevelImports) {
diff --git a/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts b/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts
index 8e4872e0c..4641b5f13 100644
--- a/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts
+++ b/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts
@@ -5,7 +5,7 @@ import { viteID } from '../util.js';
import { getPageDataByViteID } from './internal.js';
function virtualHoistedEntry(id: string) {
- return id.endsWith('.astro/hoisted.js') || id.endsWith('.md/hoisted.js');
+ return id.startsWith('/astro/hoisted.js?q=');
}
export function vitePluginHoistedScripts(
@@ -49,12 +49,13 @@ export function vitePluginHoistedScripts(
virtualHoistedEntry(output.facadeModuleId)
) {
const facadeId = output.facadeModuleId!;
- const pathname = facadeId.slice(0, facadeId.length - '/hoisted.js'.length);
-
- const vid = viteID(new URL('.' + pathname, astroConfig.root));
- const pageInfo = getPageDataByViteID(internals, vid);
- if (pageInfo) {
- pageInfo.hoistedScript = id;
+ const pages = internals.hoistedScriptIdToPagesMap.get(facadeId)!;
+ for (const pathname of pages) {
+ const vid = viteID(new URL('.' + pathname, astroConfig.root));
+ const pageInfo = getPageDataByViteID(internals, vid);
+ if (pageInfo) {
+ pageInfo.hoistedScript = id;
+ }
}
}
}