{"id":350160,"date":"2021-08-23T07:28:14","date_gmt":"2021-08-23T14:28:14","guid":{"rendered":"https:\/\/css-tricks.com\/?p=350160"},"modified":"2021-08-23T09:18:05","modified_gmt":"2021-08-23T16:18:05","slug":"native-javascript-routing","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/native-javascript-routing\/","title":{"rendered":"Native JavaScript Routing?"},"content":{"rendered":"\n

We can update the URL in JavaScript. We’ve got the APIs pushState<\/a><\/code> and replaceState<\/a><\/code>: <\/p>\n\n\n\n

\/\/ Adds to browser history\nhistory.pushState({}, \"About Page\", \"\/about\");\n\n\/\/ Doesn't\nhistory.replaceState({}, \"About Page\", \"\/about\");<\/code><\/pre>\n\n\n\n

JavaScript is also capable of replacing any content in the DOM. <\/p>\n\n\n\n

\/\/ Hardcore\ndocument.body.innerHTML = `\n  <div>New body who dis.<\/div>\n`;<\/code><\/pre>\n\n\n\n

So with those powers combined, we can build a website where we navigate to different “pages” but the browser never refreshes. That’s literally what “Single Page App” (SPA) means.<\/p>\n\n\n\n\n\n\n\n

But routing can get a bit complicated. We’re really on our own implementing it outside these somewhat low-level APIs. I’m most familiar with reaching for something like React Router<\/a>, which allows the expression of routes in JSX. Something like this:<\/p>\n\n\n\n

<Router>\n  <Switch>\n    <Route path=\"\/about\">\n      <About \/>\n    <\/Route>\n    <Route path=\"\/users\">\n      <Users \/>\n    <\/Route>\n    <Route path=\"\/user\/:id\">\n      <User id={id} \/>\n    <\/Route>\n    <Route path=\"\/\">\n      <Home \/>\n    <\/Route>\n  <\/Switch>\n<\/Router><\/code><\/pre>\n\n\n\n

The docs describe this bit like:<\/p>\n\n\n\n

A <Switch><\/code> looks through its children <Route><\/code> and renders the first one that matches the current URL.<\/p><\/blockquote>\n\n\n\n

So it’s a little bit like a RegEx matcher with API niceties, like the ability to make a “token” with something like :id<\/code> that acts as a wildcard you can pass to components to use in queries and such. <\/p>\n\n\n\n

This is work! Hence the reason we have libraries to help us. But it looks like the web platform is doing what it does best and stepping in to help where it can. Over on the Google webdev blog<\/a>, this is explained largely the same way:<\/p>\n\n\n\n

Routing is a key piece of every web application. At its heart, routing involves taking a URL, applying some pattern matching or other app-specific logic to it, and then, usually, displaying web content based on the result. Routing might be implemented in a number of ways: it’s sometimes code running on a server that maps a path to files on disk, or logic in a single-page app that waits for changes to the current location and creates a corresponding piece of DOM to display.<\/p>

While there is no one definitive standard, web developers have gravitated towards a common syntax for expressing URL routing patterns that share a lot in common with regular expressions<\/a>, but with some domain-specific additions like tokens for matching path segments.<\/p>Jeff Posnick<\/em>, “URLPattern brings routing to the web platform”<\/a><\/cite><\/blockquote>\n\n\n\n

New tech!<\/p>\n\n\n\n

const p = new URLPattern({\n  pathname: '\/foo\/:image.jpg',\n  baseURL: 'https:\/\/example.com',\n});<\/code><\/pre>\n\n\n\n

We can set up a pattern like that, and then run tests against it by shooting it a URL (probably the currently navigated-to one):<\/p>\n\n\n\n

let result = p.test('https:\/\/example.com\/foo\/cat.jpg');\n\/\/ true\n\nresult = p.exec('https:\/\/imagecdn1.example.com\/foo\/cat.jpg');\n\/\/ result.hostname.groups.subdomain will be 'imagecdn1'\n\/\/ result.pathname.groups[0] will be 'foo', corresponding to *\n\/\/ result.pathname.groups.image will be 'cat'<\/code><\/pre>\n\n\n\n

I would think the point of all this is perhaps being able to build routing into SPAs without having to reach for libraries, making for lighter\/faster websites. Or that the libraries that help us with routing can leverage it, making the libraries smaller, and ultimately websites that are lighter and faster.<\/p>\n\n\n\n

This is not solid tech yet, so probably best to just read the blog post<\/a> to get the gist. And use the polyfill<\/a> if you want to try it out. <\/p>\n\n\n\n

And speaking of the web platform showing love on SPAs lately, check out Shared Element Transitions<\/a> which seems to be re-gaining momentum. <\/p>\n","protected":false},"excerpt":{"rendered":"

We can update the URL in JavaScript. We’ve got the APIs pushState and replaceState: JavaScript is also capable of replacing any content in the DOM. So with those powers combined, we can build a website where we navigate to different “pages” but the browser never refreshes. That’s literally what “Single Page App” (SPA) means.<\/p>\n","protected":false},"author":3,"featured_media":350196,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[4],"tags":[11232,625],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/08\/js-router.png?fit=1200%2C600&ssl=1","jetpack-related-posts":[{"id":266471,"url":"https:\/\/css-tricks.com\/stimulus\/","url_meta":{"origin":350160,"position":0},"title":"Stimulus","date":"February 10, 2018","format":false,"excerpt":"A modest JavaScript framework for the HTML you already have. This will appeal to anyone who is apprehensive about JavaScript being required to generate HTML, yet wants a modern framework to help with modern problems, like state management. I wonder if this would be a good answer for things like\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":356134,"url":"https:\/\/css-tricks.com\/does-the-next-generation-of-static-site-generators-make-building-sites-better\/","url_meta":{"origin":350160,"position":1},"title":"Does the Next Generation of Static Site Generators Make Building Sites Better?","date":"November 8, 2021","format":false,"excerpt":"Just ran across \u00eeles, a new static site generator mostly centered around Vue. The world has no particular shortage of static site generators, but it's interesting to see what this \"next generation\" of SSGs seem to focus on or try to solve. \u00eeles looks to take a heaping spoonful of\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/11\/Screen-Shot-2021-11-05-at-5.48.56-AM.png?fit=1200%2C396&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":316692,"url":"https:\/\/css-tricks.com\/three-css-alternatives-to-javascript-navigation\/","url_meta":{"origin":350160,"position":2},"title":"Three CSS Alternatives to JavaScript Navigation","date":"July 14, 2020","format":false,"excerpt":"Hey quick! You\u2019ve gotta create the navigation for the site and you start working on the mobile behavior. What pattern do you choose? If you\u2019re like most folks, it\u2019s probably the \u201chamburger\u201d menu that, when clicked, uses a little JavaScript to expand a vertical list of navigation links. But that\u2019s\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/01\/hamburger-menu.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":265339,"url":"https:\/\/css-tricks.com\/routing-route-protection-server-rendered-vue-apps-using-nuxt-js\/","url_meta":{"origin":350160,"position":3},"title":"Routing and Route Protection in Server-Rendered Vue Apps Using Nuxt.js","date":"January 25, 2018","format":false,"excerpt":"You might have had some experience trying to render an app built with Vue on a server. The concept and implementation details of Server-Side Rendering (SSR) are challenging for beginners as well as experienced developers. The challenges get more daunting when you have to do things like data fetching, routing\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/01\/vue-nuxt-featured.jpg?fit=1200%2C800&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":256806,"url":"https:\/\/css-tricks.com\/simple-server-side-rendering-routing-page-transitions-nuxt-js\/","url_meta":{"origin":350160,"position":4},"title":"Simple Server Side Rendering, Routing, and Page Transitions with Nuxt.js","date":"July 24, 2017","format":false,"excerpt":"A bit of a wordy title, huh? What is server side rendering? What does it have to do with routing and page transitions? What the heck is Nuxt.js? Funnily enough, even though it sounds complex, working with Nuxt.js and exploring the benefits of isn't too difficult. Let's get started! Server\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2017\/07\/nuxt.png?fit=1116%2C448&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":343495,"url":"https:\/\/css-tricks.com\/a-look-at-building-with-astro\/","url_meta":{"origin":350160,"position":5},"title":"A Look at Building with Astro","date":"July 7, 2021","format":false,"excerpt":"Astro is a brand new framework for building websites. To me, the big thing is that it allows you to build a site like you're using a JavaScript framework (and you are), but the output is a zero-JavaScript static site. You can opt-in to client-side JavaScript as needed, and there\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/07\/social.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"featured_media_src_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/08\/js-router.png?fit=1024%2C512&ssl=1","_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/350160"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=350160"}],"version-history":[{"count":5,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/350160\/revisions"}],"predecessor-version":[{"id":350462,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/350160\/revisions\/350462"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media\/350196"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=350160"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=350160"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=350160"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}