refactor(astro): emit entry.mjs to import pages via dynamic import (#7036)

This commit is contained in:
Emanuele Stoppa 2023-05-19 15:30:03 +01:00 committed by GitHub
parent 96947fce96
commit 852d59a8d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 24 additions and 10 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Emit pages as dynamic import chunks during the build

View file

@ -139,7 +139,7 @@ export class App {
defaultStatus = 404; defaultStatus = 404;
} }
let mod = this.#manifest.pageMap.get(routeData.component)!; let mod = await this.#manifest.pageMap.get(routeData.component)!();
if (routeData.type === 'page') { if (routeData.type === 'page') {
let response = await this.#renderPage(request, routeData, mod, defaultStatus); let response = await this.#renderPage(request, routeData, mod, defaultStatus);
@ -148,7 +148,7 @@ export class App {
if (response.status === 500) { if (response.status === 500) {
const fiveHundredRouteData = matchRoute('/500', this.#manifestData); const fiveHundredRouteData = matchRoute('/500', this.#manifestData);
if (fiveHundredRouteData) { if (fiveHundredRouteData) {
mod = this.#manifest.pageMap.get(fiveHundredRouteData.component)!; mod = await this.#manifest.pageMap.get(fiveHundredRouteData.component)!();
try { try {
let fiveHundredResponse = await this.#renderPage( let fiveHundredResponse = await this.#renderPage(
request, request,

View file

@ -31,6 +31,7 @@ export interface RouteInfo {
export type SerializedRouteInfo = Omit<RouteInfo, 'routeData'> & { export type SerializedRouteInfo = Omit<RouteInfo, 'routeData'> & {
routeData: SerializedRouteData; routeData: SerializedRouteData;
}; };
type ImportComponentInstance = () => Promise<ComponentInstance>;
export interface SSRManifest { export interface SSRManifest {
adapterName: string; adapterName: string;
@ -39,7 +40,7 @@ export interface SSRManifest {
base?: string; base?: string;
assetsPrefix?: string; assetsPrefix?: string;
markdown: MarkdownRenderingOptions; markdown: MarkdownRenderingOptions;
pageMap: Map<ComponentPath, ComponentInstance>; pageMap: Map<ComponentPath, ImportComponentInstance>;
renderers: SSRLoadedRenderer[]; renderers: SSRLoadedRenderer[];
/** /**
* Map of directive name (e.g. `load`) to the directive script code * Map of directive name (e.g. `load`) to the directive script code

View file

@ -169,15 +169,15 @@ async function generatePage(
.map(({ sheet }) => sheet) .map(({ sheet }) => sheet)
.reduce(mergeInlineCss, []); .reduce(mergeInlineCss, []);
const pageModule = ssrEntry.pageMap?.get(pageData.component); const pageModulePromise = ssrEntry.pageMap?.get(pageData.component);
const middleware = ssrEntry.middleware; const middleware = ssrEntry.middleware;
if (!pageModule) { if (!pageModulePromise) {
throw new Error( throw new Error(
`Unable to find the module for ${pageData.component}. This is unexpected and likely a bug in Astro, please report.` `Unable to find the module for ${pageData.component}. This is unexpected and likely a bug in Astro, please report.`
); );
} }
const pageModule = await pageModulePromise();
if (shouldSkipDraft(pageModule, opts.settings)) { if (shouldSkipDraft(pageModule, opts.settings)) {
info(opts.logging, null, `${magenta('⚠️')} Skipping draft ${pageData.route.component}`); info(opts.logging, null, `${magenta('⚠️')} Skipping draft ${pageData.route.component}`);
return; return;

View file

@ -42,7 +42,10 @@ export function* walkParentInfos(
// Returns true if a module is a top-level page. We determine this based on whether // Returns true if a module is a top-level page. We determine this based on whether
// it is imported by the top-level virtual module. // it is imported by the top-level virtual module.
export function moduleIsTopLevelPage(info: ModuleInfo): boolean { export function moduleIsTopLevelPage(info: ModuleInfo): boolean {
return info.importers[0] === resolvedPagesVirtualModuleId; return (
info.importers[0] === resolvedPagesVirtualModuleId ||
info.dynamicImporters[0] == resolvedPagesVirtualModuleId
);
} }
// This function walks the dependency graph, going up until it finds a page component. // This function walks the dependency graph, going up until it finds a page component.

View file

@ -29,7 +29,9 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V
let i = 0; let i = 0;
for (const pageData of eachPageData(internals)) { for (const pageData of eachPageData(internals)) {
const variable = `_page${i}`; const variable = `_page${i}`;
imports.push(`import * as ${variable} from ${JSON.stringify(pageData.moduleSpecifier)};`); imports.push(
`const ${variable} = () => import(${JSON.stringify(pageData.moduleSpecifier)});`
);
importMap += `[${JSON.stringify(pageData.component)}, ${variable}],`; importMap += `[${JSON.stringify(pageData.component)}, ${variable}],`;
i++; i++;
} }

View file

@ -3,6 +3,7 @@ import type { BuildInternals } from '../internal.js';
import type { AstroBuildPlugin } from '../plugin.js'; import type { AstroBuildPlugin } from '../plugin.js';
import type { StaticBuildOptions } from '../types'; import type { StaticBuildOptions } from '../types';
import { extendManualChunks } from './util.js'; import { extendManualChunks } from './util.js';
import path from 'node:path';
function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals): VitePlugin { function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals): VitePlugin {
return { return {
@ -25,7 +26,7 @@ function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals
} }
pageInfo.route.prerender = false; pageInfo.route.prerender = false;
// dynamic pages should all go in their own chunk in the pages/* directory // dynamic pages should all go in their own chunk in the pages/* directory
return `pages/all`; return `pages/${path.basename(pageInfo.component)}`;
} }
}, },
}); });

View file

@ -47,8 +47,10 @@ export interface StaticBuildOptions {
teardownCompiler: boolean; teardownCompiler: boolean;
} }
type ImportComponentInstance = () => Promise<ComponentInstance>;
export interface SingleFileBuiltModule { export interface SingleFileBuiltModule {
pageMap: Map<ComponentPath, ComponentInstance>; pageMap: Map<ComponentPath, ImportComponentInstance>;
middleware: AstroMiddlewareInstance<unknown>; middleware: AstroMiddlewareInstance<unknown>;
renderers: SSRLoadedRenderer[]; renderers: SSRLoadedRenderer[];
} }