Skip to content
This repository has been archived by the owner on Jul 19, 2020. It is now read-only.

URL Fragment Routing #150

Closed
pythoneer opened this issue Oct 24, 2019 · 6 comments · Fixed by #177
Closed

URL Fragment Routing #150

pythoneer opened this issue Oct 24, 2019 · 6 comments · Fixed by #177
Labels
breaking change This change will result in a broken build or differing behavior in end-user crates. enhancement New feature or request exploration This feature may not be possible to implement. low priority Other work will take precedence over this. Speed of work may be dependent on external interest.

Comments

@pythoneer
Copy link

Description
In the recent pull request #133 with an addition to the readme, it is suggested to configure the server in a specific way. I think this is at least a little bit problematic and there needs to be a solution coming entirely form the frontend that is less intrusive to the server.

Other frameworks solve this problem be "encoding" the route as an URL Fragment

To reiterate on the problem:
if one has a route to www.example.com/user/12/detail the browser would request a document from the server at the location www.example.com/user/12/detail/index.html that is not present thus resulting in a 404. The current suggestion is layed out in #133 .

The proposed solution would be to use URL Fragments (also known as named anchors) to prevent the browser to request a new document from the server altogether. The route translated to the example above would look like this www.example.com/#/user/12/detail

prior art: https://angular.io/api/common/HashLocationStrategy

Downside: it's old and probably obsolete where html5 pushState exists. Its still "problematic" for entry point / shared links.

@pythoneer pythoneer added the enhancement New feature or request label Oct 24, 2019
@hgzimmerman
Copy link
Member

Fragment based routing is possible to a very limited degree at the moment, although the parser is partially limited in the allowed syntax (eg, currently it doesn't allow ? or / to appear after a #).

Defining all of your routes like #[to="#route"] is possible, but due to the restrictions on / not appearing after #, you are only limited to a single path segment, which severely limits the viability of this approach.

I personally don't like fragment based routing as it strikes me as outdated and ugly as mentioned, and people should be encouraged to use the full route instead, but I don't see a reason to prevent it if it could otherwise be done - given how it saves effort of setting up the server in a certain way.

A reasonable alteration to address this suggestion would be to make the parser less strict in what it is able to parse in the fragment section, so that normal routes can be expressed there.

@hgzimmerman hgzimmerman added the low priority Other work will take precedence over this. Speed of work may be dependent on external interest. label Oct 25, 2019
@hgzimmerman hgzimmerman added the exploration This feature may not be possible to implement. label Oct 25, 2019
@hgzimmerman
Copy link
Member

hgzimmerman commented Oct 26, 2019

Ok, taking a look at all the links you sent. I like the idea of HashLocationStrategy. Configuring the RouteService (and by extension, the RouteAgent) with a default type parameter that controls if a # is prepended to the route when setting and matching the browser's location seems to be the best way to accomplish this.

Something like:

pub struct RouteService<STATE, R: RouteBehavior = NoOp> {...}

It allows for the parser to remain unchanged, allows for a reasonable default, and for customization of routing behavior at compile-time.


EDIT:
This change is breaking, and it will arrive in a 0.7.0 release

@hgzimmerman hgzimmerman added the breaking change This change will result in a broken build or differing behavior in end-user crates. label Oct 26, 2019
@pythoneer
Copy link
Author

This sounds like a very reasonable way towards a solution.

@hgzimmerman
Copy link
Member

hgzimmerman commented Nov 4, 2019

Thinking about this issue as I'm about to implement it, I don't think that a default type parameter is as good of a solution that I thought.

Because Yew uses specific type information to look up agents, every type that depends on the RouteAgent needs to have a bridge or dispatcher connecting to the exact same RouteAgent type. This allows for possible misuse when someone wants to use a plain RouteButton to set the route for a RouteAgent<Frag> instantiated by a Router<Frag>. The plain button will spawn a RouteAgent<PlainRoute> and set the route, bypassing the RouteAgent<Frag> used by the router. In addition to setting the route incorrectly, the Router also wouldn't receive a message telling it to update, because it isn't connected to the agent issuing the updates.

As a consequence of this, some stateful flag needs to be passed to the RouterService, and a special message must be created on the agent in order to enable this setting.

@hgzimmerman
Copy link
Member

I have settled on just making the parser more permissive, accepting pretty much arbitrary tokens after a # is encountered (except these characters "!{}", which still operate as expected). I think adding type parameters would be error prone, and adding state to the agent/service to represent that a # should be inserted/ignored before the rest of the route would be inelegant and similarly error prone.

It is unfortunate that you will now have to sprinkle # at the beginnings of every route if you want to use fragment routing, but this is the most expedient and arguably best way to get fragment routing working.

@pythoneer
Copy link
Author

Thanks for putting so much though into it! I believe that the use of this feature will continue to decline over time and a less intrusive solution sounds like the way to go.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
breaking change This change will result in a broken build or differing behavior in end-user crates. enhancement New feature or request exploration This feature may not be possible to implement. low priority Other work will take precedence over this. Speed of work may be dependent on external interest.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants