Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Routing is FUN - the Web is weird, but fun

Tags: route path router

Posted on Oct 18 Have you ever wondered how Routers work in frameworks and such? I did not. Until I had to write one for Cardboard. I discovered that they're actually pretty fun to build, and not at all weird or hacky.Well, I've lied a bit. They're weird and a bit hacky, but pretty fun to figure out. I also more or less understood how they worked (after years of using many of them), but not what goes into them in the backend. The basic concept is that whenever we navigate to a new URL Path, we need to show some content that's linked to that path. But do not reload the page, just change the content.For example, if navigating to /home, we need to show the content for the /home Route. If navigating to the /about page, we need to show the content of the /about route. And of course, when we show content, we must hide the previous content.That's the basics of what a router does. There's more than that, but I'll get to that.One thing we need before being able to create the router we must first understand how URL changes work and how we can detect when a path change happens.What do I mean by path change? Well, changing the pathname part of the URL. For example, from this https://test.com/ to this https://test.com/home.How do we do this in JS? There are a couple of ways of doing this, for example:It works, but we need to set the whole URL instead of just changing the path. The problem with this? You can't change the path relative to the current one. This means that, if you're at /home/ideas, and want to change to /home/contact. We must set the whole path: location.pathname = "/home/contact".Another problem with this approach is that every time we change the location, the page will reload. You can imagine why this is not good for SPAs. For single-page apps, we don't want to reload the whole page each time the path changes.Imagine we're at /home/ideas, and we run this:It will change the path from /home/ideas to /home/contact. This can be done very easily by using the history.pushState()Okay, that's cool and all, but how do we detect when the path changes? Well, HTML has an event that made me hopeful: popstate. But it only fires when you go back in the history (i.e. page back).And, of course, of course, there's no event for the pushstate... why would there be!I might be wrong though, but I've not been able to find an event for when pushState is called. If you know how please let me know!So, what I've come up with is, to modify the pushState function and inject some custom logic into it. I don't really like this approach as we're modifying stuff we should not, but it's the only way I've found. This is what I mean:Now we can listen to pushstate events like the popstate one:Now that we can detect when the path changes we can add the logic that will change the contents of the page based on that path.I will show a very basic example. But know that in reality there's a lot more stuff behind the scenes to make it work, and to make it more efficient. The first thing we need is a way of configuring the routes of our app. In this example, we'll have a function (makeRouter) to handle that. I will not show the complete function as it's a bit long for the example.makeRouter needs a couple of things, an object with the content for each route we want to have (opts.routes), and a selector to know where to put the contents (opts.parentSelector). routes will be an object with the route path as a key and a function as the value. Imagine that these functions return Cardboard components. These components will represent some HTML and logic that will be on the page when the route is viewed.myRouter is an instance of the router object. It should also be possible to get a router from other parts of the app. Imagine there is some magic function (getRouter) that returns the current router.The router object allows us to navigate between routes:This uses the history.pushState in the background to update the URL in the browser, and, as we've overridden the pushState method, the pushstate event will be fired. Behind the scenes, makeRouter does a couple of things to make everything work:Now, what happens if the route is not defined for a path? Currently, everything will break! But we can add some more features to our router to make it more secure and ergonomic.First let's add a fallback route, for when a route is not found, we can default to that route.Fairly easy, when creating the router, we must now ask for another option (opts.fallbackRoute), which will just be the route path.Now, if a route is not found, it will show the /home route. We could also allow the makeRouter function to receive an option for a route builder (opts.noRouteBuilder). This allows us to pass in a function for when the route is invalid:Much better, now whilst we have fallbackRoute and that route exits, or we have noRouteBuilder we'll not have errors. But what if the fallback route does not exist? or no builder is passed? Well, currently, everything will break.There are a few ways of handling this, and this should be up to each implementation. In my case, I decided that instead of throwing some error, or requiring the fallback or builder, I would just add an error to the page instead, indicating that the route does not exist!Well, this might be the most complex part of the process, and it all depends on the context where you're building the router. Is it a router for a framework that already exists? Does it need to work in vanilla JS? Is it the core router for your framework? After knowing the context ask yourself: Can I do this already in some way? Can I show/hide content with the framework? Do I need to implement it myself? Is there some tool out there that can help me?These are some of the questions you will need to ask yourself. And based on the answers you will do this in one way or another. In my case, as I was building this for Cardboard, and had already implemented a way of adding and removing items from the page very easily and efficiently, I made use of that. I will show a little pseudo-code example showcasing the updatePage function mentioned above. This function will run each time the path changes (on pushstate or popstate).This is extremely simple, but the concept is as follows:This example just scratched the surface, there are a lot more improvements that could be done to make it a fully fletched router. Here are some of them:So yeah, I think that sums up what a router is and how to create one. Of course not in detail, it will not work if you just copy and paste. I think tutorials or guides like these should not just give you the answer, they should make you think, problem-solve, and more importantly learn. But give a clear view of how it works and show some of the oddities and quirks. I hope this article has done some of that for you!Let me know your thoughts: Do you like this style of tutorial/guide? Or do you prefer a more step-by-step kind of article?Cheers! That's me for this one. Have a nice one :)Feedback needed: I'm currently working on Cardboard, pouring all my love, and free time into it (it's a lot, I'm unemployed). But I need early feedback to make sure it starts in the best way possible. Can I ask you to kindly head over to the Cardboard repo, take a look at the project, and give me some feedback? The project is open for anyone to help. You can contact me here on DEV, by mail: [email protected], drop an issue, or comment on this post!Templates let you quickly answer FAQs or store snippets for re-use.Respond to this comment to add your feedback! :) Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well Confirm For further actions, you may consider blocking this person and/or reporting abuse Muhammad Furqan - Oct 16 rodrigozan - Oct 16 Eckehard - Oct 16 Basti Ortiz - Oct 15 Once suspended, nombrekeff will not be able to comment or publish posts until their suspension is removed. Once unsuspended, nombrekeff will be able to comment and publish posts again. Once unpublished, all posts by nombrekeff will become hidden and only accessible to themselves. If nombrekeff is not suspended, they can still re-publish their posts from their dashboard. Note: Once unpublished, this post will become invisible to the public and only accessible to Keff. They can still re-publish the post if they are not suspended. Thanks for keeping DEV Community safe. Here is what you can do to flag nombrekeff: nombrekeff consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy. Unflagging nombrekeff will restore default visibility to their posts. DEV Community — A constructive and inclusive social network for software developers. With you every step of your journey. Built on Forem — the open source software that powers DEV and other inclusive communities.Made with love and Ruby on Rails. DEV Community © 2016 - 2023. We're a place where coders share, stay up-to-date and grow their careers.



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

Routing is FUN - the Web is weird, but fun

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×