Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
Original issue: #2132. In short, the performance of adding a large number of routes is slow, and is particularly problematic with SSR.
This PR explores the idea of a 'pluggable matcher'. This allows the matcher to be passed into the router, rather than being created internally. The potential benefits are twofold:
The code presented here is a long way from being merged, but hopefully it'll work as a starting point to discuss how to proceed.
SSR usage
To get the benefits with SSR, we'd need to replace this:
with this:
The
clone()
call creates a copy of the matcher, allowing for more routes to be added or removed without impacting the original matcher.The performance of this is really good. Calling
clone()
is very fast and we skip all the overhead of processing the individual routes.Custom matchers
This is trickier.
The usage is similar to the previous example, but with a custom implementation of
matcher
.TypeScript isn't my strong suit, so perhaps this isn't as difficult as it seemed, but I found trying to get the types working as I wanted really difficult. The code in this PR is much less ambitious than some of my other attempts, but hopefully it'll still illustrate the difficulties.
For example, I tried writing a custom matcher that only supported the options
path
,name
,component
andcomponents
. You can see that at:If you search through the code for
Pain point
, you'll find various points where I had to do things that didn't really make sense in the context of that matcher implementation. Some of those may be necessary for other reasons, but in many cases I was adding things just to appease TS. For example, thescore
andre
properties are completely redundant, but the types force them to be included.I did experiment with changing those types, adding generics all over the place, but it got a bit out of hand and I decided to aim a little lower for this initial PR. Instead, I chose to focus just on the route config.
As
SimpleRouterMatcher
only supports 4 options for the route, I wanted the types to reflect that. SoSimpleRoute
is a type that defines that format, with the matcher having type:You'll find
RC
used a generic in various places in the code.RC
stands for 'route config'.This then has an impact on the type of the
addRoute()
method of the router itself. New routes need to be added using theSimpleRoute
format. e.g.:This almost works. The major problem is
$router
anduseRouter()
, neither of which take account of the generic.Other problems
The
options
property of theRouter
type is a bit fiddly. It needs to take account of the options passed tocreateRouterWithMatcher()
, which aren't the same ascreateRouter()
.Next steps
If we just want the performance benefits for SSR usage, we don't need support for custom matchers. That would dodge most of the type problems.
The custom matcher feature may tie into #2148. That PR is currently implemented as changes to the default matcher, but it could instead be implemented as a separate matcher implementation.
If the type problems can be overcome, I think we'd also need to consider adding helpers to make custom matchers easier to write. I found myself duplicating a lot of logic from the default matcher when I was writing
SimpleRouterMatcher
. If we do choose to pursue this further, I recommend anyone wanting to give feedback to attempt writing a custom matcher. I found going through that process quite enlightening.Depending on what direction we choose to go in, we should also consider an RFC. At the very least we'd need some feedback from the SSR meta-frameworks about whether this is workable for them.
Relationship to other PRs