From 71814d78fcac7afd53d0732e9ae13ca8e6667bf7 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 28 Nov 2023 08:23:06 -0500 Subject: [PATCH 1/4] Write index routes as index.html with build.format: 'file' --- packages/astro/src/@types/astro.ts | 1 + packages/astro/src/core/build/common.ts | 28 ++++++++++++++----- packages/astro/src/core/build/generate.ts | 4 +-- .../astro/src/core/routing/manifest/create.ts | 3 ++ .../page-format/src/pages/nested/index.astro | 8 ++++++ packages/astro/test/page-format.test.js | 6 ++++ 6 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 packages/astro/test/fixtures/page-format/src/pages/nested/index.astro diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index e77222c0c165..02227203e648 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -2363,6 +2363,7 @@ export interface RouteData { redirect?: RedirectConfig; redirectRoute?: RouteData; fallbackRoutes: RouteData[]; + index: boolean; } export type RedirectRouteData = RouteData & { diff --git a/packages/astro/src/core/build/common.ts b/packages/astro/src/core/build/common.ts index e7efc6439e4e..c973f15f5472 100644 --- a/packages/astro/src/core/build/common.ts +++ b/packages/astro/src/core/build/common.ts @@ -1,6 +1,6 @@ import npath from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; -import type { AstroConfig, RouteType } from '../../@types/astro.js'; +import type { AstroConfig, RouteData } from '../../@types/astro.js'; import { appendForwardSlash } from '../../core/path.js'; const STATUS_CODE_PAGES = new Set(['/404', '/500']); @@ -17,9 +17,10 @@ function getOutRoot(astroConfig: AstroConfig): URL { export function getOutFolder( astroConfig: AstroConfig, pathname: string, - routeType: RouteType + routeData: RouteData ): URL { const outRoot = getOutRoot(astroConfig); + const routeType = routeData.type; // This is the root folder to write to. switch (routeType) { @@ -36,8 +37,15 @@ export function getOutFolder( return new URL('.' + appendForwardSlash(pathname), outRoot); } case 'file': { - const d = pathname === '' ? pathname : npath.dirname(pathname); - return new URL('.' + appendForwardSlash(d), outRoot); + let dir; + // If the pathname is '' then this is the root index.html + // If this is an index route, the folder should be the pathname, not the parent + if(pathname === '' || routeData.index) { + dir = pathname; + } else { + dir = npath.dirname(pathname); + } + return new URL('.' + appendForwardSlash(dir), outRoot); } } } @@ -47,8 +55,9 @@ export function getOutFile( astroConfig: AstroConfig, outFolder: URL, pathname: string, - routeType: RouteType + routeData: RouteData ): URL { + const routeType = routeData.type; switch (routeType) { case 'endpoint': return new URL(npath.basename(pathname), outFolder); @@ -64,8 +73,13 @@ export function getOutFile( return new URL('./index.html', outFolder); } case 'file': { - const baseName = npath.basename(pathname); - return new URL('./' + (baseName || 'index') + '.html', outFolder); + let baseName = npath.basename(pathname); + // If there is no base name this is the root route. + // If this is an index route, the name should be `index.html`. + if(!baseName || routeData.index) { + baseName = 'index'; + } + return new URL(`./${baseName}.html`, outFolder); } } } diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index a7d286b4054c..1550c9c39463 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -601,8 +601,8 @@ async function generatePath(pathname: string, gopts: GeneratePathOptions, pipeli body = Buffer.from(await response.arrayBuffer()); } - const outFolder = getOutFolder(pipeline.getConfig(), pathname, route.type); - const outFile = getOutFile(pipeline.getConfig(), outFolder, pathname, route.type); + const outFolder = getOutFolder(pipeline.getConfig(), pathname, route); + const outFile = getOutFile(pipeline.getConfig(), outFolder, pathname, route); route.distURL = outFile; await fs.promises.mkdir(outFolder, { recursive: true }); diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts index 7c04638ac5a8..f6f3e9af47ac 100644 --- a/packages/astro/src/core/routing/manifest/create.ts +++ b/packages/astro/src/core/routing/manifest/create.ts @@ -347,6 +347,7 @@ export function createRouteManifest( generate, pathname: pathname || undefined, prerender, + index: item.isIndex, fallbackRoutes: [], }); } @@ -424,6 +425,7 @@ export function createRouteManifest( pathname: pathname || void 0, prerender: prerenderInjected ?? prerender, fallbackRoutes: [], + index: false, }); }); @@ -464,6 +466,7 @@ export function createRouteManifest( redirect: to, redirectRoute: routes.find((r) => r.route === to), fallbackRoutes: [], + index: false, }; const lastSegmentIsDynamic = (r: RouteData) => !!r.segments.at(-1)?.at(-1)?.dynamic; diff --git a/packages/astro/test/fixtures/page-format/src/pages/nested/index.astro b/packages/astro/test/fixtures/page-format/src/pages/nested/index.astro new file mode 100644 index 000000000000..9c077e2a381b --- /dev/null +++ b/packages/astro/test/fixtures/page-format/src/pages/nested/index.astro @@ -0,0 +1,8 @@ + + + Testing + + +

Testing

+ + diff --git a/packages/astro/test/page-format.test.js b/packages/astro/test/page-format.test.js index 2143bf09b263..5c99da7ef6d9 100644 --- a/packages/astro/test/page-format.test.js +++ b/packages/astro/test/page-format.test.js @@ -47,6 +47,12 @@ describe('build.format', () => { let $ = cheerio.load(html); expect($('#another').attr('href')).to.equal('/nested/another/'); }); + + it('index files are written as index.html', async () => { + let html = await fixture.readFile('/nested/index.html'); + let $ = cheerio.load(html); + expect($('h1').text()).to.equal('Testing'); + }); }); }); }); From a7d75753ecf89461e8b55d972696704f78981ce4 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 28 Nov 2023 08:34:38 -0500 Subject: [PATCH 2/4] Add a changeset --- .changeset/tame-flies-confess.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .changeset/tame-flies-confess.md diff --git a/.changeset/tame-flies-confess.md b/.changeset/tame-flies-confess.md new file mode 100644 index 000000000000..6c4d7f333075 --- /dev/null +++ b/.changeset/tame-flies-confess.md @@ -0,0 +1,11 @@ +--- +'astro': major +--- + +build.format: 'file' now honors index routes + +Prior to Astro 4, using `build.format: 'file'`, a method to produce HTML files that are *not* all within folders, would only produce `index.html` for the base path of `/`. This meant that even if you created explicit index pages with, for example, `page/index.astro`, it would write these out as `page.html`. + +This was unexpected behavior as `build.format: 'file'` is intended to match the file system routing exactly. Now in Astro 4 it does, with index routes being written just as they are in your source directly. `page/index.astro` becomes `page/index.html`. + +This change only affects SSG when using `build.format: 'file'`. From f0cd02ce98e66756c0bf270590ec90037c26064d Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 28 Nov 2023 08:38:14 -0500 Subject: [PATCH 3/4] types --- packages/astro/src/core/build/plugins/plugin-manifest.ts | 4 ++-- packages/astro/src/core/routing/manifest/serialization.ts | 1 + packages/astro/src/vite-plugin-astro-server/route.ts | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/astro/src/core/build/plugins/plugin-manifest.ts b/packages/astro/src/core/build/plugins/plugin-manifest.ts index 0ac0db028823..daef83a84e87 100644 --- a/packages/astro/src/core/build/plugins/plugin-manifest.ts +++ b/packages/astro/src/core/build/plugins/plugin-manifest.ts @@ -176,8 +176,8 @@ function buildManifest( if (!route.prerender) continue; if (!route.pathname) continue; - const outFolder = getOutFolder(opts.settings.config, route.pathname, route.type); - const outFile = getOutFile(opts.settings.config, outFolder, route.pathname, route.type); + const outFolder = getOutFolder(opts.settings.config, route.pathname, route); + const outFile = getOutFile(opts.settings.config, outFolder, route.pathname, route); const file = outFile.toString().replace(opts.settings.config.build.client.toString(), ''); routes.push({ file, diff --git a/packages/astro/src/core/routing/manifest/serialization.ts b/packages/astro/src/core/routing/manifest/serialization.ts index f70aa84dd0ac..51dda41c17eb 100644 --- a/packages/astro/src/core/routing/manifest/serialization.ts +++ b/packages/astro/src/core/routing/manifest/serialization.ts @@ -38,5 +38,6 @@ export function deserializeRouteData(rawRouteData: SerializedRouteData): RouteDa fallbackRoutes: rawRouteData.fallbackRoutes.map((fallback) => { return deserializeRouteData(fallback); }), + index: rawRouteData.index, }; } diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts index 4c49525e7593..01cdfa6cb1e3 100644 --- a/packages/astro/src/vite-plugin-astro-server/route.ts +++ b/packages/astro/src/vite-plugin-astro-server/route.ts @@ -216,6 +216,7 @@ export async function handleRoute({ type: 'fallback', route: '', fallbackRoutes: [], + index: false, }; renderContext = await createRenderContext({ request, From a619adcd3b55947705cbd2d2eb2c4571fa0add4d Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 28 Nov 2023 08:45:50 -0500 Subject: [PATCH 4/4] Update outdated tests --- packages/astro/test/astro-pageDirectoryUrl.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/astro/test/astro-pageDirectoryUrl.test.js b/packages/astro/test/astro-pageDirectoryUrl.test.js index 978db056aebc..c97b8d402e58 100644 --- a/packages/astro/test/astro-pageDirectoryUrl.test.js +++ b/packages/astro/test/astro-pageDirectoryUrl.test.js @@ -16,7 +16,7 @@ describe('build format', () => { it('outputs', async () => { expect(await fixture.readFile('/client.html')).to.be.ok; - expect(await fixture.readFile('/nested-md.html')).to.be.ok; - expect(await fixture.readFile('/nested-astro.html')).to.be.ok; + expect(await fixture.readFile('/nested-md/index.html')).to.be.ok; + expect(await fixture.readFile('/nested-astro/index.html')).to.be.ok; }); });