From ba0636240996f9f082d122a8414240196881cb96 Mon Sep 17 00:00:00 2001 From: Arsh <69170106+lilnasy@users.noreply.github.com> Date: Mon, 22 May 2023 18:45:21 +0530 Subject: [PATCH] fix(hoisted scripts): consider script's dependents (#7144) --- .changeset/perfect-oranges-tease.md | 5 ++ .../build/plugins/plugin-hoisted-scripts.ts | 69 +++++++++++-------- 2 files changed, 44 insertions(+), 30 deletions(-) create mode 100644 .changeset/perfect-oranges-tease.md diff --git a/.changeset/perfect-oranges-tease.md b/.changeset/perfect-oranges-tease.md new file mode 100644 index 000000000000..a5aca06f4205 --- /dev/null +++ b/.changeset/perfect-oranges-tease.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixed an issue where scripts that weren't safe to inline were inlined. diff --git a/packages/astro/src/core/build/plugins/plugin-hoisted-scripts.ts b/packages/astro/src/core/build/plugins/plugin-hoisted-scripts.ts index 38d8323848da..4c9b48597882 100644 --- a/packages/astro/src/core/build/plugins/plugin-hoisted-scripts.ts +++ b/packages/astro/src/core/build/plugins/plugin-hoisted-scripts.ts @@ -4,7 +4,7 @@ import { viteID } from '../../util.js'; import type { BuildInternals } from '../internal.js'; import { getPageDataByViteID } from '../internal.js'; import type { AstroBuildPlugin } from '../plugin'; -import type { StaticBuildOptions } from '../types'; +import type { OutputChunk, StaticBuildOptions } from '../types'; function virtualHoistedEntry(id: string) { return id.startsWith('/astro/hoisted.js?q='); @@ -50,46 +50,55 @@ export function vitePluginHoistedScripts( assetInlineLimit = settings.config.vite?.build.assetsInlineLimit; } + const considerInlining = new Map(); + const importedByOtherScripts = new Set(); + // Find all page entry points and create a map of the entry point to the hashed hoisted script. // This is used when we render so that we can add the script to the head. - for (const [id, output] of Object.entries(bundle)) { + Object.entries(bundle).forEach(([ id, output ]) => { if ( output.type === 'chunk' && output.facadeModuleId && virtualHoistedEntry(output.facadeModuleId) ) { - const canBeInlined = - output.imports.length === 0 && - output.dynamicImports.length === 0 && - Buffer.byteLength(output.code) <= assetInlineLimit; - let removeFromBundle = false; - const facadeId = output.facadeModuleId!; - const pages = internals.hoistedScriptIdToPagesMap.get(facadeId)!; - for (const pathname of pages) { - const vid = viteID(new URL('.' + pathname, settings.config.root)); - const pageInfo = getPageDataByViteID(internals, vid); - if (pageInfo) { - if (canBeInlined) { - pageInfo.hoistedScript = { - type: 'inline', - value: output.code, - }; - removeFromBundle = true; - } else { - pageInfo.hoistedScript = { - type: 'external', - value: id, - }; - } + considerInlining.set(id, output); + output.imports.forEach(imported => importedByOtherScripts.add(imported)); + } + }); + + for (const [ id, output ] of considerInlining.entries()) { + const canBeInlined = + importedByOtherScripts.has(output.fileName) === false && + output.imports.length === 0 && + output.dynamicImports.length === 0 && + Buffer.byteLength(output.code) <= assetInlineLimit; + let removeFromBundle = false; + const facadeId = output.facadeModuleId!; + const pages = internals.hoistedScriptIdToPagesMap.get(facadeId)!; + for (const pathname of pages) { + const vid = viteID(new URL('.' + pathname, settings.config.root)); + const pageInfo = getPageDataByViteID(internals, vid); + if (pageInfo) { + if (canBeInlined) { + pageInfo.hoistedScript = { + type: 'inline', + value: output.code, + }; + removeFromBundle = true; + } else { + pageInfo.hoistedScript = { + type: 'external', + value: id, + }; } } + } - // Remove the bundle if it was inlined - if (removeFromBundle) { - delete bundle[id]; - } + // Remove the bundle if it was inlined + if (removeFromBundle) { + delete bundle[id]; } - } + }; }, }; }