diff --git a/.changeset/clean-bags-mate.md b/.changeset/clean-bags-mate.md new file mode 100644 index 000000000..9f6b7058d --- /dev/null +++ b/.changeset/clean-bags-mate.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Revert hoisted scripts analysis to prevent missing scripts during build diff --git a/packages/astro/src/core/build/plugins/plugin-analyzer.ts b/packages/astro/src/core/build/plugins/plugin-analyzer.ts index c05328005..b650e04f1 100644 --- a/packages/astro/src/core/build/plugins/plugin-analyzer.ts +++ b/packages/astro/src/core/build/plugins/plugin-analyzer.ts @@ -1,11 +1,9 @@ -import type { ModuleInfo, PluginContext } from 'rollup'; +import type { PluginContext } from 'rollup'; import type { Plugin as VitePlugin } from 'vite'; import type { PluginMetadata as AstroPluginMetadata } from '../../../vite-plugin-astro/types'; import type { BuildInternals } from '../internal.js'; import type { AstroBuildPlugin } from '../plugin.js'; -import type { ExportDefaultDeclaration, ExportNamedDeclaration, ImportDeclaration } from 'estree'; -import { walk } from 'estree-walker'; import { PROPAGATED_ASSET_FLAG } from '../../../content/consts.js'; import { prependForwardSlash } from '../../../core/path.js'; import { getTopLevelPages, moduleIsTopLevelPage, walkParentInfos } from '../graph.js'; @@ -19,102 +17,6 @@ function isPropagatedAsset(id: string) { } } -/** - * @returns undefined if the parent does not import the child, string[] of the reexports if it does - */ -async function doesParentImportChild( - this: PluginContext, - parentInfo: ModuleInfo, - childInfo: ModuleInfo | undefined, - childExportNames: string[] | 'dynamic' | undefined -): Promise<'no' | 'dynamic' | string[]> { - if (!childInfo || !parentInfo.ast || !childExportNames) return 'no'; - - if (childExportNames === 'dynamic' || parentInfo.dynamicallyImportedIds?.includes(childInfo.id)) { - return 'dynamic'; - } - - const imports: Array = []; - const exports: Array = []; - walk(parentInfo.ast, { - enter(node) { - if (node.type === 'ImportDeclaration') { - imports.push(node as ImportDeclaration); - } else if ( - node.type === 'ExportDefaultDeclaration' || - node.type === 'ExportNamedDeclaration' - ) { - exports.push(node as ExportNamedDeclaration | ExportDefaultDeclaration); - } - }, - }); - // All of the aliases the current component is imported as - const importNames: string[] = []; - // All of the aliases the child component is exported as - const exportNames: string[] = []; - - for (const node of imports) { - const resolved = await this.resolve(node.source.value as string, parentInfo.id); - if (!resolved || resolved.id !== childInfo.id) continue; - for (const specifier of node.specifiers) { - // TODO: handle these? - if (specifier.type === 'ImportNamespaceSpecifier') continue; - const name = - specifier.type === 'ImportDefaultSpecifier' ? 'default' : specifier.imported.name; - // If we're importing the thing that the child exported, store the local name of what we imported - if (childExportNames.includes(name)) { - importNames.push(specifier.local.name); - } - } - } - for (const node of exports) { - if (node.type === 'ExportDefaultDeclaration') { - if (node.declaration.type === 'Identifier' && importNames.includes(node.declaration.name)) { - exportNames.push('default'); - // return - } - } else { - // handle `export { x } from 'something';`, where the export and import are in the same node - if (node.source) { - const resolved = await this.resolve(node.source.value as string, parentInfo.id); - if (!resolved || resolved.id !== childInfo.id) continue; - for (const specifier of node.specifiers) { - if (childExportNames.includes(specifier.local.name)) { - importNames.push(specifier.local.name); - exportNames.push(specifier.exported.name); - } - } - } - if (node.declaration) { - if (node.declaration.type !== 'VariableDeclaration') continue; - for (const declarator of node.declaration.declarations) { - if (declarator.init?.type !== 'Identifier') continue; - if (declarator.id.type !== 'Identifier') continue; - if (importNames.includes(declarator.init.name)) { - exportNames.push(declarator.id.name); - } - } - } - for (const specifier of node.specifiers) { - if (importNames.includes(specifier.local.name)) { - exportNames.push(specifier.exported.name); - } - } - } - } - if (!importNames.length) return 'no'; - - // If the component is imported by another component, assume it's in use - // and start tracking this new component now - if (parentInfo.id.endsWith('.astro')) { - exportNames.push('default'); - } else if (parentInfo.id.endsWith('.mdx')) { - exportNames.push('Content'); - } - - return exportNames; -} - export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { function hoistedScriptScanner() { const uniqueHoistedIds = new Map(); @@ -127,11 +29,7 @@ export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { >(); return { - async scan( - this: PluginContext, - scripts: AstroPluginMetadata['astro']['scripts'], - from: string - ) { + scan(this: PluginContext, scripts: AstroPluginMetadata['astro']['scripts'], from: string) { const hoistedScripts = new Set(); for (let i = 0; i < scripts.length; i++) { const hid = `${from.replace('/@fs', '')}?astro&type=script&index=${i}&lang.ts`; @@ -139,35 +37,9 @@ export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { } if (hoistedScripts.size) { - const depthsToChildren = new Map(); - const depthsToExportNames = new Map(); - // The component export from the original component file will always be default. - depthsToExportNames.set(0, ['default']); - - for (const [parentInfo, depth] of walkParentInfos(from, this, function until(importer) { + for (const [parentInfo] of walkParentInfos(from, this, function until(importer) { return isPropagatedAsset(importer); })) { - depthsToChildren.set(depth, parentInfo); - // If at any point - if (depth > 0) { - // Check if the component is actually imported: - const childInfo = depthsToChildren.get(depth - 1); - const childExportNames = depthsToExportNames.get(depth - 1); - - const doesImport = await doesParentImportChild.call( - this, - parentInfo, - childInfo, - childExportNames - ); - - if (doesImport === 'no') { - // Break the search if the parent doesn't import the child. - continue; - } - depthsToExportNames.set(depth, doesImport); - } - if (isPropagatedAsset(parentInfo.id)) { for (const [nestedParentInfo] of walkParentInfos(from, this)) { if (moduleIsTopLevelPage(nestedParentInfo)) { @@ -274,7 +146,7 @@ export function vitePluginAnalyzer(internals: BuildInternals): VitePlugin { } // Scan hoisted scripts - await hoistScanner.scan.call(this, astro.scripts, id); + hoistScanner.scan.call(this, astro.scripts, id); if (astro.clientOnlyComponents.length) { const clientOnlys: string[] = []; diff --git a/packages/astro/test/hoisted-imports.test.js b/packages/astro/test/hoisted-imports.test.js index 973d7103e..5d18a7be5 100644 --- a/packages/astro/test/hoisted-imports.test.js +++ b/packages/astro/test/hoisted-imports.test.js @@ -2,7 +2,8 @@ import { expect } from 'chai'; import { loadFixture } from './test-utils.js'; import * as cheerio from 'cheerio'; -describe('Hoisted Imports', () => { +// Skip for now until we can implement a better hoisted scripts solution +describe.skip('Hoisted Imports', () => { let fixture; before(async () => {