Revert hoisted scripts analysis (#7707)
This commit is contained in:
parent
4d160fa1e2
commit
15b4276dc4
3 changed files with 11 additions and 133 deletions
5
.changeset/clean-bags-mate.md
Normal file
5
.changeset/clean-bags-mate.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Revert hoisted scripts analysis to prevent missing scripts during build
|
|
@ -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<ImportDeclaration> = [];
|
||||
const exports: Array<ExportNamedDeclaration | ExportDefaultDeclaration> = [];
|
||||
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<string, string>();
|
||||
|
@ -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<string>();
|
||||
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<number, ModuleInfo>();
|
||||
const depthsToExportNames = new Map<number, string[] | 'dynamic'>();
|
||||
// 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[] = [];
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
Loading…
Reference in a new issue