-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Implement priority overrides for injected routes and redirects #9439
Changes from 6 commits
9f6a7e9
a6671a8
bf8a333
31885a9
06bcec2
8a61bb7
a475688
c211704
0c678b2
7379e1d
a064b4e
cea5439
9dd4609
addd2d9
e3cbbe9
d5e2142
322bb4d
28df92f
a368d60
dc2760a
7cfbdbd
61fc289
eb855b9
a8686b8
e319eb4
bd93047
de3a8cb
fdc7c90
5671f41
24c9c74
7fc2482
30241b6
fb78e03
dcf8ca4
9882de1
a34647e
dd8c15f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
--- | ||
'astro': minor | ||
--- | ||
|
||
Reworks route priority processing to allow for more flexible and intuitive redirects and route injection | ||
|
||
- Priority order for project routes, injected routes and redirects are now all the same. | ||
- Injected routes and redirects can now specify if they should be prioritized above, | ||
with or below project routes. This is done by adding a `priority` property to the route | ||
object in `injectRoute` and in the `redirects` property in `astro.config.mjs`. | ||
- Now more specific routes always take priority over less specific routes. | ||
Example: `/blog/[...slug]` will take priority over `/[...slug]` | ||
- Static redirects now have a lower priority than all project routed, even if the routes are dynamic, | ||
matching the already documented behavior. | ||
Example: `/blog (redirect)` will no longer override a `/[slug]` route by default, this can be re-enabled | ||
using the new `priority` field. | ||
- Collision detection between routes can now detect coliisions between similar dynamic routes | ||
of any kind (project routes, injected routes and redirects). | ||
Example: `/blog/[page]` will now be detected as a collision with `/blog/[slug]` | ||
- Colision detection is now reported as a warning for backward compatibility with all the previous false negatives. |
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -1555,10 +1555,19 @@ export interface AstroUserConfig { | |||||||||||||||||
*/ | ||||||||||||||||||
export type InjectedScriptStage = 'before-hydration' | 'head-inline' | 'page' | 'page-ssr'; | ||||||||||||||||||
|
||||||||||||||||||
/** | ||||||||||||||||||
* IDs for different priorities of injected routes and redirects: | ||||||||||||||||||
Fryuni marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
* - "above-project": Override any project route in case of conflict. | ||||||||||||||||||
* - "same-as-project": Behave the same as if the route was defined in the project, following the same priority rules. | ||||||||||||||||||
* - "below-project": Only match if no project route matches. | ||||||||||||||||||
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. @withastro/maintainers-docs You should focus here. Naming is very important here 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. I think the naming should involve file-based routing somehow, rather than project. Took me a second to realize that's what project meant. 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. I also wonder if “above”/“below” is ideal. I understand why it was chosen, but I associate high/low more with priority. Maybe something like this could work? @sarah11918 is also a good person to bounce these off. I don’t love “file-system” here — not sure it’s super clear that this means “file-based route” or if there’s something clearer. Could there ever be other kinds of priority? If not, it could be redundant to mention that in the enum values and the options could just be
Suggested change
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. Another option would be to use a number, with all project routes having priority zero, injected routes defaulting to a priority of -1 and redirects defaulting to a priority of 1. Then the other rules apply for when this number is the same. This may be easier to document and even more flexible. Maybe too flexible and would make things confusing for integration developers. 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. Yes, I’d caution against that I think. Even if internally the enum maps to 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. I like that direction @sarah11918! 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. I also liked @sarah11918's suggestion. I'll send a commit with those and change from just "project routes" to "project file-based routes" to make it clear what they are relative to. 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. Just sent a commit with a new suggestion. I first used the terms by @sarah11918, but it felt weird to have a priority named "default" that is not the default, so I went with "merge". Also changed the "project routes" to clarify that those are the routes inferred from files. What do you all think? Better, worse, still confusing? 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. Right, I agree not to use default as an option that is not the default. 😀
If you wanted the "conform" (follow the rules) angle, then other synonyms could be I'm not sure I have a strong preference. Just highlighting some options to see if one immediately jumps out at you! 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. Out of those, I think I still prefer |
||||||||||||||||||
*/ | ||||||||||||||||||
export type RoutePriorityOverride = 'above-project' | 'same-as-project' | 'below-project'; | ||||||||||||||||||
|
||||||||||||||||||
export interface InjectedRoute { | ||||||||||||||||||
pattern: string; | ||||||||||||||||||
entrypoint: string; | ||||||||||||||||||
prerender?: boolean; | ||||||||||||||||||
priority?: RoutePriorityOverride; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
export interface ResolvedInjectedRoute extends InjectedRoute { | ||||||||||||||||||
|
@@ -2385,6 +2394,7 @@ type RedirectConfig = | |||||||||||||||||
| { | ||||||||||||||||||
status: ValidRedirectStatus; | ||||||||||||||||||
destination: string; | ||||||||||||||||||
priority?: RoutePriorityOverride; | ||||||||||||||||||
}; | ||||||||||||||||||
|
||||||||||||||||||
export interface RouteData { | ||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -173,6 +173,7 @@ export const AstroConfigSchema = z.object({ | |||||||||
z.literal(308), | ||||||||||
]), | ||||||||||
destination: z.string(), | ||||||||||
priority: z.enum(['above-project', 'same-as-project', 'below-project']).optional(), | ||||||||||
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. I believe we should at least provide a default. 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. The default is added where it is used, but I can also add it here. I didn't do it because then there would be a risk of the defaults becoming out of sync. If the redirect uses just the destination string instead of an object, there is no priority in the configuration, so the default has to be where it is used. 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.
From this phrase, I understand "where it is used" and this configuration aren't the same. Did I understand correctly? 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. Yes, I mean the code on 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. Is the configuration ever not passed through this schema? I think what @ematipico is suggesting is this:
Suggested change
This ensures 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. Redirects can be just a string: {
redirects: {
'/foo': '/bar'
}
} So the code code on 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. You could use a Zod transform to do that upfront too, iiuc! 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. Using a transform now! |
||||||||||
}), | ||||||||||
]) | ||||||||||
) | ||||||||||
|
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.
Let me know when this is considered finalized behaviour/naming etc, and please
/ptal
me for a review at that time!