From 852d59a8d68e124f10852609e0f1619d5838ac76 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 19 May 2023 15:30:03 +0100 Subject: [PATCH] refactor(astro): emit `entry.mjs` to import pages via dynamic import (#7036) --- .changeset/popular-rules-provide.md | 5 +++++ packages/astro/src/core/app/index.ts | 4 ++-- packages/astro/src/core/app/types.ts | 3 ++- packages/astro/src/core/build/generate.ts | 6 +++--- packages/astro/src/core/build/graph.ts | 5 ++++- packages/astro/src/core/build/plugins/plugin-pages.ts | 4 +++- packages/astro/src/core/build/plugins/plugin-prerender.ts | 3 ++- packages/astro/src/core/build/types.ts | 4 +++- 8 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 .changeset/popular-rules-provide.md diff --git a/.changeset/popular-rules-provide.md b/.changeset/popular-rules-provide.md new file mode 100644 index 000000000..ada5a2da0 --- /dev/null +++ b/.changeset/popular-rules-provide.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Emit pages as dynamic import chunks during the build diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index 546d45975..078d43e50 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -139,7 +139,7 @@ export class App { defaultStatus = 404; } - let mod = this.#manifest.pageMap.get(routeData.component)!; + let mod = await this.#manifest.pageMap.get(routeData.component)!(); if (routeData.type === 'page') { let response = await this.#renderPage(request, routeData, mod, defaultStatus); @@ -148,7 +148,7 @@ export class App { if (response.status === 500) { const fiveHundredRouteData = matchRoute('/500', this.#manifestData); if (fiveHundredRouteData) { - mod = this.#manifest.pageMap.get(fiveHundredRouteData.component)!; + mod = await this.#manifest.pageMap.get(fiveHundredRouteData.component)!(); try { let fiveHundredResponse = await this.#renderPage( request, diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts index 89c5bad37..3747e96e3 100644 --- a/packages/astro/src/core/app/types.ts +++ b/packages/astro/src/core/app/types.ts @@ -31,6 +31,7 @@ export interface RouteInfo { export type SerializedRouteInfo = Omit & { routeData: SerializedRouteData; }; +type ImportComponentInstance = () => Promise; export interface SSRManifest { adapterName: string; @@ -39,7 +40,7 @@ export interface SSRManifest { base?: string; assetsPrefix?: string; markdown: MarkdownRenderingOptions; - pageMap: Map; + pageMap: Map; renderers: SSRLoadedRenderer[]; /** * Map of directive name (e.g. `load`) to the directive script code diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index 452a902ca..5a9f075c4 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -169,15 +169,15 @@ async function generatePage( .map(({ sheet }) => sheet) .reduce(mergeInlineCss, []); - const pageModule = ssrEntry.pageMap?.get(pageData.component); + const pageModulePromise = ssrEntry.pageMap?.get(pageData.component); const middleware = ssrEntry.middleware; - if (!pageModule) { + if (!pageModulePromise) { throw new Error( `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)) { info(opts.logging, null, `${magenta('⚠️')} Skipping draft ${pageData.route.component}`); return; diff --git a/packages/astro/src/core/build/graph.ts b/packages/astro/src/core/build/graph.ts index 6d7335c09..68d264b10 100644 --- a/packages/astro/src/core/build/graph.ts +++ b/packages/astro/src/core/build/graph.ts @@ -42,7 +42,10 @@ export function* walkParentInfos( // 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. 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. diff --git a/packages/astro/src/core/build/plugins/plugin-pages.ts b/packages/astro/src/core/build/plugins/plugin-pages.ts index 68967c390..80e28b0ee 100644 --- a/packages/astro/src/core/build/plugins/plugin-pages.ts +++ b/packages/astro/src/core/build/plugins/plugin-pages.ts @@ -29,7 +29,9 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V let i = 0; for (const pageData of eachPageData(internals)) { 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}],`; i++; } diff --git a/packages/astro/src/core/build/plugins/plugin-prerender.ts b/packages/astro/src/core/build/plugins/plugin-prerender.ts index 7c9f3f784..6ea846c0a 100644 --- a/packages/astro/src/core/build/plugins/plugin-prerender.ts +++ b/packages/astro/src/core/build/plugins/plugin-prerender.ts @@ -3,6 +3,7 @@ import type { BuildInternals } from '../internal.js'; import type { AstroBuildPlugin } from '../plugin.js'; import type { StaticBuildOptions } from '../types'; import { extendManualChunks } from './util.js'; +import path from 'node:path'; function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals): VitePlugin { return { @@ -25,7 +26,7 @@ function vitePluginPrerender(opts: StaticBuildOptions, internals: BuildInternals } pageInfo.route.prerender = false; // dynamic pages should all go in their own chunk in the pages/* directory - return `pages/all`; + return `pages/${path.basename(pageInfo.component)}`; } }, }); diff --git a/packages/astro/src/core/build/types.ts b/packages/astro/src/core/build/types.ts index d04f7476c..c0f38de45 100644 --- a/packages/astro/src/core/build/types.ts +++ b/packages/astro/src/core/build/types.ts @@ -47,8 +47,10 @@ export interface StaticBuildOptions { teardownCompiler: boolean; } +type ImportComponentInstance = () => Promise; + export interface SingleFileBuiltModule { - pageMap: Map; + pageMap: Map; middleware: AstroMiddlewareInstance; renderers: SSRLoadedRenderer[]; }