-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updates the dev server to handle multiple routes matching the same URL #4087
Changes from 1 commit
0c1bb3f
4cdfd66
47ea99e
c260b9b
d3dd9af
f8ef6e5
023f6bc
5785ada
2cf2440
03a253e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
export { createRouteManifest } from './manifest/create.js'; | ||
export { deserializeRouteData, serializeRouteData } from './manifest/serialization.js'; | ||
export { matchRoute } from './match.js'; | ||
export { matchRoute, matchAllRoutes } from './match.js'; | ||
export { getParams } from './params.js'; | ||
export { validateGetStaticPathsModule, validateGetStaticPathsResult } from './validation.js'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ import { getParamsAndProps, GetParamsAndPropsError } from '../core/render/core.j | |
import { preload, ssr } from '../core/render/dev/index.js'; | ||
import { RouteCache } from '../core/render/route-cache.js'; | ||
import { createRequest } from '../core/request.js'; | ||
import { createRouteManifest, matchRoute } from '../core/routing/index.js'; | ||
import { createRouteManifest, matchAllRoutes, matchRoute } from '../core/routing/index.js'; | ||
import { createSafeError, resolvePages } from '../core/util.js'; | ||
import notFoundTemplate, { subpathNotUsedTemplate } from '../template/4xx.js'; | ||
|
||
|
@@ -248,26 +248,72 @@ async function handleRequest( | |
clientAddress: buildingToSSR ? req.socket.remoteAddress : undefined, | ||
}); | ||
|
||
async function matchRoute() { | ||
const matches = matchAllRoutes(pathname, manifest); | ||
|
||
for await (const maybeRoute of matches) { | ||
const filePath = new URL(`./${maybeRoute.component}`, config.root); | ||
const preloadedComponent = await preload({ astroConfig: config, filePath, viteServer }); | ||
const [, mod] = preloadedComponent; | ||
// attempt to get static paths | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this result in getStaticPaths being called more than once? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's still only called once. The Just noticed we have a test to make sure it's only called once but that test only covers |
||
// if this fails, we have a bad URL match! | ||
const paramsAndPropsRes = await getParamsAndProps({ | ||
mod, | ||
route: maybeRoute, | ||
routeCache, | ||
pathname: pathname, | ||
logging, | ||
ssr: config.output === 'server', | ||
}); | ||
|
||
if (paramsAndPropsRes !== GetParamsAndPropsError.NoMatchingStaticPath) { | ||
return { | ||
route: maybeRoute, | ||
filePath, | ||
preloadedComponent, | ||
mod, | ||
} | ||
} | ||
} | ||
|
||
if (matches.length) { | ||
warn( | ||
logging, | ||
'getStaticPaths', | ||
`Route pattern matched, but no matching static path found. (${pathname})` | ||
); | ||
} | ||
|
||
log404(logging, pathname); | ||
const custom404 = getCustom404Route(config, manifest); | ||
|
||
if (custom404) { | ||
const filePath = new URL(`./${custom404.component}`, config.root); | ||
const preloadedComponent = await preload({ astroConfig: config, filePath, viteServer }); | ||
const [, mod] = preloadedComponent; | ||
|
||
return { | ||
route: custom404, | ||
filePath, | ||
preloadedComponent, | ||
mod | ||
}; | ||
} | ||
|
||
return undefined; | ||
} | ||
|
||
let filePath: URL | undefined; | ||
try { | ||
// Attempt to match the URL to a valid page route. | ||
// If that fails, switch the response to a 404 response. | ||
let route = matchRoute(pathname, manifest); | ||
const statusCode = route ? 200 : 404; | ||
const matchedRoute = await matchRoute(); | ||
|
||
if (!route) { | ||
log404(logging, pathname); | ||
const custom404 = getCustom404Route(config, manifest); | ||
if (custom404) { | ||
route = custom404; | ||
} else { | ||
return handle404Response(origin, config, req, res); | ||
} | ||
if (!matchedRoute) { | ||
return handle404Response(origin, config, req, res); | ||
} | ||
|
||
filePath = new URL(`./${route.component}`, config.root); | ||
const preloadedComponent = await preload({ astroConfig: config, filePath, viteServer }); | ||
const [, mod] = preloadedComponent; | ||
const { route, preloadedComponent, mod } = matchedRoute; | ||
filePath = matchedRoute.filePath; | ||
|
||
// attempt to get static paths | ||
// if this fails, we have a bad URL match! | ||
const paramsAndPropsRes = await getParamsAndProps({ | ||
|
@@ -278,38 +324,6 @@ async function handleRequest( | |
logging, | ||
ssr: config.output === 'server', | ||
}); | ||
if (paramsAndPropsRes === GetParamsAndPropsError.NoMatchingStaticPath) { | ||
warn( | ||
logging, | ||
'getStaticPaths', | ||
`Route pattern matched, but no matching static path found. (${pathname})` | ||
); | ||
log404(logging, pathname); | ||
const routeCustom404 = getCustom404Route(config, manifest); | ||
if (routeCustom404) { | ||
const filePathCustom404 = new URL(`./${routeCustom404.component}`, config.root); | ||
const preloadedCompCustom404 = await preload({ | ||
astroConfig: config, | ||
filePath: filePathCustom404, | ||
viteServer, | ||
}); | ||
const result = await ssr(preloadedCompCustom404, { | ||
astroConfig: config, | ||
filePath: filePathCustom404, | ||
logging, | ||
mode: 'development', | ||
origin, | ||
pathname: pathname, | ||
request, | ||
route: routeCustom404, | ||
routeCache, | ||
viteServer, | ||
}); | ||
return await writeSSRResult(result, res); | ||
} else { | ||
return handle404Response(origin, config, req, res); | ||
} | ||
} | ||
|
||
const options: SSROptions = { | ||
astroConfig: config, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
export async function getStaticPaths() { | ||
return [ | ||
{ | ||
params: { page: "page-1" } | ||
}, | ||
{ | ||
params: { page: "page-2" } | ||
} | ||
] | ||
} | ||
--- | ||
|
||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width" /> | ||
<title>Routing</title> | ||
</head> | ||
|
||
<body> | ||
<h1>[page].astro</h1> | ||
<p>{Astro.params.page}</p> | ||
</body> | ||
|
||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
export async function getStaticPaths() { | ||
return [ | ||
{ | ||
params: { slug: "slug-1" }, | ||
}, | ||
{ | ||
params: { slug: "slug-2" }, | ||
} | ||
] | ||
} | ||
--- | ||
|
||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width" /> | ||
<title>Routing</title> | ||
</head> | ||
|
||
<body> | ||
<h1>[slug].astro</h1> | ||
<p>{Astro.params.slug}</p> | ||
</body> | ||
|
||
</html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
used by the dev server to find all potential routes for the requested URL