mirror of
https://github.com/withastro/astro.git
synced 2024-12-30 22:03:56 -05:00
Fix dynamic prerender conflict (#10298)
* Reproduce issues * Handle inconsistency between static, dynamic and rest routes * Add extra test cases * Add changeset * Revert unrelated changes * Update lockfile
This commit is contained in:
parent
c99bbd09af
commit
819d20a89c
17 changed files with 322 additions and 2 deletions
5
.changeset/strange-forks-exist.md
Normal file
5
.changeset/strange-forks-exist.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"astro": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix an incorrect conflict resolution between pages generated from static routes and rest parameters
|
|
@ -326,7 +326,7 @@ async function getPathsForRoute(
|
||||||
let paths: Array<string> = [];
|
let paths: Array<string> = [];
|
||||||
if (route.pathname) {
|
if (route.pathname) {
|
||||||
paths.push(route.pathname);
|
paths.push(route.pathname);
|
||||||
builtPaths.add(route.pathname);
|
builtPaths.add(removeTrailingForwardSlash(route.pathname));
|
||||||
} else {
|
} else {
|
||||||
const staticPaths = await callGetStaticPaths({
|
const staticPaths = await callGetStaticPaths({
|
||||||
mod,
|
mod,
|
||||||
|
|
|
@ -37,5 +37,13 @@ export function getRouteGenerator(
|
||||||
trailing = '/';
|
trailing = '/';
|
||||||
}
|
}
|
||||||
const toPath = compile(template + trailing);
|
const toPath = compile(template + trailing);
|
||||||
return toPath;
|
return (params: object): string => {
|
||||||
|
const path = toPath(params);
|
||||||
|
|
||||||
|
// When generating an index from a rest parameter route, `path-to-regexp` will return an
|
||||||
|
// empty string instead "/". This causes an inconsistency with static indexes that may result
|
||||||
|
// in the incorrect routes being rendered.
|
||||||
|
// To fix this, we return "/" when the path is empty.
|
||||||
|
return path || '/';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
59
packages/astro/test/dynamic-route-collision.test.js
Normal file
59
packages/astro/test/dynamic-route-collision.test.js
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { before, describe, it } from 'node:test';
|
||||||
|
import * as cheerio from 'cheerio';
|
||||||
|
import { loadFixture } from './test-utils.js';
|
||||||
|
|
||||||
|
describe('Dynamic route collision', () => {
|
||||||
|
/** @type {import('./test-utils').Fixture} */
|
||||||
|
let fixture;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
fixture = await loadFixture({
|
||||||
|
root: './fixtures/dynamic-route-collision',
|
||||||
|
});
|
||||||
|
|
||||||
|
await fixture.build().catch(console.log);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Builds a static route when in conflict with a dynamic route', async () => {
|
||||||
|
const html = await fixture.readFile('/about/index.html');
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
assert.equal($('h1').text(), 'Static About');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Builds a static route when in conflict with a spread route', async () => {
|
||||||
|
const html = await fixture.readFile('/who/index.html');
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
assert.equal($('h1').text(), 'Static Who We Are');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Builds a static nested index when in conflict with a spread route', async () => {
|
||||||
|
const html = await fixture.readFile('/tags/index.html');
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
assert.equal($('h1').text(), 'Static Tags Index');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Builds a static root index when in conflict with a spread route', async () => {
|
||||||
|
const html = await fixture.readFile('/index.html');
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
assert.equal($('h1').text(), 'Static Index');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Builds a static index a nested when in conflict with a dynamic+spread route', async () => {
|
||||||
|
const html = await fixture.readFile('/en/index.html');
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
assert.equal($('h1').text(), 'Dynamic-only Localized Index');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Builds a dynamic route when in conflict with a spread route', async () => {
|
||||||
|
const html = await fixture.readFile('/blog/index.html');
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
assert.equal($('h1').text(), 'Dynamic Blog');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Builds the highest priority route out of two conflicting dynamic routes', async () => {
|
||||||
|
const html = await fixture.readFile('/order/index.html');
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
assert.equal($('h1').text(), 'Order from A');
|
||||||
|
});
|
||||||
|
});
|
8
packages/astro/test/fixtures/dynamic-route-collision/package.json
vendored
Normal file
8
packages/astro/test/fixtures/dynamic-route-collision/package.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "@test/dynamic-route-collision",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"astro": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
35
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[...slug].astro
vendored
Normal file
35
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[...slug].astro
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const pages = [
|
||||||
|
{
|
||||||
|
slug: undefined,
|
||||||
|
title: 'Rest Index',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'blog',
|
||||||
|
title: 'Rest Blog',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'who',
|
||||||
|
title: 'Rest Who We Are',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return pages.map(({ slug, title }) => {
|
||||||
|
return {
|
||||||
|
params: { slug },
|
||||||
|
props: { title },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
27
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[aOrder].astro
vendored
Normal file
27
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[aOrder].astro
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const pages = [
|
||||||
|
{
|
||||||
|
page: 'order',
|
||||||
|
title: 'Order from A',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return pages.map(({ page, title }) => {
|
||||||
|
return {
|
||||||
|
params: { 'aOrder': page },
|
||||||
|
props: { title },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
27
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[bOrder].astro
vendored
Normal file
27
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[bOrder].astro
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const pages = [
|
||||||
|
{
|
||||||
|
page: 'order',
|
||||||
|
title: 'Order from B',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return pages.map(({ page, title }) => {
|
||||||
|
return {
|
||||||
|
params: { 'bOrder': page },
|
||||||
|
props: { title },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
28
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[locale]/[...page].astro
vendored
Normal file
28
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[locale]/[...page].astro
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const pages = [
|
||||||
|
{
|
||||||
|
locale: 'en',
|
||||||
|
page: undefined,
|
||||||
|
title: 'Dynamic+Rest Localized Index',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return pages.map(({ page, locale, title }) => {
|
||||||
|
return {
|
||||||
|
params: { page, locale },
|
||||||
|
props: { title },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
27
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[locale]/index.astro
vendored
Normal file
27
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[locale]/index.astro
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const pages = [
|
||||||
|
{
|
||||||
|
locale: 'en',
|
||||||
|
title: 'Dynamic-only Localized Index',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return pages.map(({ page, locale, title }) => {
|
||||||
|
return {
|
||||||
|
params: { page, locale },
|
||||||
|
props: { title },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
31
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[page].astro
vendored
Normal file
31
packages/astro/test/fixtures/dynamic-route-collision/src/pages/[page].astro
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const pages = [
|
||||||
|
{
|
||||||
|
page: 'about',
|
||||||
|
title: 'Dynamic About',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
page: 'blog',
|
||||||
|
title: 'Dynamic Blog',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return pages.map(({ page, title }) => {
|
||||||
|
return {
|
||||||
|
params: { page },
|
||||||
|
props: { title },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
8
packages/astro/test/fixtures/dynamic-route-collision/src/pages/about.astro
vendored
Normal file
8
packages/astro/test/fixtures/dynamic-route-collision/src/pages/about.astro
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Static About Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Static About</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
8
packages/astro/test/fixtures/dynamic-route-collision/src/pages/index.astro
vendored
Normal file
8
packages/astro/test/fixtures/dynamic-route-collision/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Static Index Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Static Index</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
27
packages/astro/test/fixtures/dynamic-route-collision/src/pages/tags/[...page].astro
vendored
Normal file
27
packages/astro/test/fixtures/dynamic-route-collision/src/pages/tags/[...page].astro
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const pages = [
|
||||||
|
{
|
||||||
|
page: undefined,
|
||||||
|
title: 'Rest Tag Index',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return pages.map(({ page, title }) => {
|
||||||
|
return {
|
||||||
|
params: { tag: page },
|
||||||
|
props: { title },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
8
packages/astro/test/fixtures/dynamic-route-collision/src/pages/tags/index.astro
vendored
Normal file
8
packages/astro/test/fixtures/dynamic-route-collision/src/pages/tags/index.astro
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Static Tags Index</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Static Tags Index</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
8
packages/astro/test/fixtures/dynamic-route-collision/src/pages/who.astro
vendored
Normal file
8
packages/astro/test/fixtures/dynamic-route-collision/src/pages/who.astro
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Static Who We Are</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Static Who We Are</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -2732,6 +2732,12 @@ importers:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../..
|
version: link:../../..
|
||||||
|
|
||||||
|
packages/astro/test/fixtures/dynamic-route-collision:
|
||||||
|
dependencies:
|
||||||
|
astro:
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../..
|
||||||
|
|
||||||
packages/astro/test/fixtures/entry-file-names:
|
packages/astro/test/fixtures/entry-file-names:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/preact':
|
'@astrojs/preact':
|
||||||
|
|
Loading…
Reference in a new issue