diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index 3a5641e87..906a5b0ab 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -1,3 +1,4 @@ +import type { InputHTMLOptions } from '@web/rollup-plugin-html'; import type { AstroConfig, ComponentInstance, GetStaticPathsResult, ManifestData, RouteCache, RouteData, RSSResult } from '../../@types/astro-core'; import type { LogOptions } from '../logger'; @@ -69,49 +70,46 @@ class AstroBuilder { const viteServer = await vite.createServer(viteConfig); // 2. get all routes - const allPages: Promise<{ html: string; name: string }>[] = []; + const input: InputHTMLOptions[] = []; const assets: Record = {}; // additional assets to be written - await Promise.all( - this.manifest.routes.map(async (route) => { - const { pathname } = route; - const filePath = new URL(`./${route.component}`, this.config.projectRoot); - // static pages - if (pathname) { - allPages.push( - ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname, viteServer }).then((html) => ({ - html, - name: pathname.replace(/\/?$/, '/index.html').replace(/^\//, ''), - })) + for (const route of this.manifest.routes) { + const { pathname } = route; + const filePath = new URL(`./${route.component}`, this.config.projectRoot); + // static pages (note: should these be ) + if (pathname) { + input.push( + await ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname, viteServer }).then((html) => ({ + html, + name: pathname.replace(/\/?$/, '/index.html').replace(/^\//, ''), + })) + ); + } + // dynamic pages + else { + const staticPaths = await this.getStaticPathsForRoute(route, viteServer); + // handle RSS (TODO: improve this?) + if (staticPaths.rss && staticPaths.rss.xml) { + const rssFile = new URL(staticPaths.rss.url.replace(/^\/?/, './'), this.config.dist); + if (assets[fileURLToPath(rssFile)]) { + throw new Error( + `[getStaticPaths] RSS feed ${staticPaths.rss.url} already exists.\nUse \`rss(data, {url: '...'})\` to choose a unique, custom URL. (${route.component})` + ); + } + assets[fileURLToPath(rssFile)] = staticPaths.rss.xml; + } + // TODO: throw error if conflict + for (const staticPath of staticPaths.paths) { + input.push( + await ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname: staticPath, viteServer }).then( + (html) => ({ + html, + name: staticPath.replace(/\/?$/, '/index.html').replace(/^\//, ''), + }) + ) ); } - // dynamic pages - else { - const staticPaths = await this.getStaticPathsForRoute(route, viteServer); - // handle RSS (TODO: improve this?) - if (staticPaths.rss && staticPaths.rss.xml) { - const rssFile = new URL(staticPaths.rss.url.replace(/^\/?/, './'), this.config.dist); - if (assets[fileURLToPath(rssFile)]) { - throw new Error( - `[getStaticPaths] RSS feed ${staticPaths.rss.url} already exists.\nUse \`rss(data, {url: '...'})\` to choose a unique, custom URL. (${route.component})` - ); - } - assets[fileURLToPath(rssFile)] = staticPaths.rss.xml; - } - // TODO: throw error if conflict - staticPaths.paths.forEach((staticPath) => { - allPages.push( - ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname: staticPath, viteServer }).then( - (html) => ({ - html, - name: staticPath.replace(/\/?$/, '/index.html').replace(/^\//, ''), - }) - ) - ); - }); - } - }) - ); - const input = await Promise.all(allPages); + } + } // 3. build with Vite await vite.build({ @@ -177,6 +175,7 @@ class AstroBuilder { validateGetStaticPathsModule(mod); const rss = generateRssFunction(this.config.buildOptions.site, route); const staticPaths: GetStaticPathsResult = (await mod.getStaticPaths!({ paginate: generatePaginateFunction(route), rss: rss.generator })).flat(); + this.routeCache[route.component] = staticPaths; validateGetStaticPathsResult(staticPaths, this.logging); return { paths: staticPaths.map((staticPath) => staticPath.params && route.generate(staticPath.params)).filter(Boolean), diff --git a/packages/astro/src/core/ssr/index.ts b/packages/astro/src/core/ssr/index.ts index 1a36449b1..04e4e6d74 100644 --- a/packages/astro/src/core/ssr/index.ts +++ b/packages/astro/src/core/ssr/index.ts @@ -77,10 +77,10 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna // Important this happens before load module in case a renderer provides polyfills. const renderers = await resolveRenderers(viteServer, astroConfig.renderers); - // 1.5. load module + // 2. load module const mod = (await viteServer.ssrLoadModule(fileURLToPath(filePath))) as ComponentInstance; - // 2. handle dynamic routes + // 3. handle dynamic routes let params: Params = {}; let pageProps: Props = {}; if (route && !route.pathname) { @@ -91,9 +91,8 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna } } validateGetStaticPathsModule(mod); - routeCache[route.component] = - routeCache[route.component] || - ( + if (!routeCache[route.component]) { + routeCache[route.component] = await ( await mod.getStaticPaths!({ paginate: generatePaginateFunction(route), rss: () => { @@ -101,6 +100,7 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna }, }) ).flat(); + } validateGetStaticPathsResult(routeCache[route.component], logging); const routePathParams: GetStaticPathsResult = routeCache[route.component]; const matchedStaticPath = routePathParams.find(({ params: _params }) => JSON.stringify(_params) === JSON.stringify(params)); @@ -110,7 +110,7 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna pageProps = { ...matchedStaticPath.props } || {}; } - // 3. render page + // 4. render page const Component = await mod.default; if (!Component) throw new Error(`Expected an exported Astro component but received typeof ${typeof Component}`); @@ -144,12 +144,12 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna let html = await renderPage(result, Component, pageProps, null); - // 4. modify response + // 5. modify response if (mode === 'development') { html = await viteServer.transformIndexHtml(fileURLToPath(filePath), html, pathname); } - // 5. finish + // 6. finish return html; } catch (e: any) { viteServer.ssrFixStacktrace(e); diff --git a/packages/astro/test/astro-get-static-paths.test.js b/packages/astro/test/astro-get-static-paths.test.js index 735d19288..88add6234 100644 --- a/packages/astro/test/astro-get-static-paths.test.js +++ b/packages/astro/test/astro-get-static-paths.test.js @@ -1,7 +1,5 @@ -/** - * UNCOMMENT: fix "Error: can only be called once!" import { expect } from 'chai'; -import { loadFixture } from './test-utils'; +import { loadFixture } from './test-utils.js'; let fixture; @@ -22,6 +20,3 @@ describe('getStaticPaths()', () => { expect(true).to.equal(true); }); }); -*/ - -it.skip('is skipped', () => {}); diff --git a/packages/astro/test/fixtures/astro-get-static-paths/src/pages/[...test].astro b/packages/astro/test/fixtures/astro-get-static-paths/src/pages/[...test].astro index ac763c135..438a31454 100644 --- a/packages/astro/test/fixtures/astro-get-static-paths/src/pages/[...test].astro +++ b/packages/astro/test/fixtures/astro-get-static-paths/src/pages/[...test].astro @@ -1,5 +1,5 @@ --- -export function getStaticPaths({paginate}) { +export function getStaticPaths({ paginate }) { if (globalThis.isCalledOnce) { throw new Error("Can only be called once!"); } @@ -10,7 +10,7 @@ export function getStaticPaths({paginate}) { {params: {test: 'c'}}, ]; } -const { params} = Astro.request; +const { params } = Astro.request; ---