Sync or Async

With Curi, routes can be synchronous or asynchronous. By default, routes are synchronous. If a route has a resolve function, it becomes async.

When a navigation event is triggered (e.g. clicking a link or button), the router will match a route. If the route is synchronous, the response will be emitted immediately. If the route is asynchronous, the response will not be emitted until the route's async functions have finished. Asynchronous routes are useful for code splitting and preloading data.

// sync
{ name: "Home", path: "" },

// async
  name: "User",
  path: "user/:id,
  // any functions in here makes the route async
  resolve() {
    return import("./components/User");

Async Things to Think About

For the most part, it shouldn't matter to you (or your users) whether routes are sync or async, but there are a couple of things that you should be aware of when it comes to async matching.

  1. If the initial route that matches is async and you try to render immediately, the response will be undefined. You can wait to render until the initial response is ready with router.once.

    let router = createRouter(browser, routes);
    router.once(() => {
      // the initial response is ready,
      // so it is safe to render
  2. With async routes, there is a delay between when the user clicks a link and when the new response is emitted (the delay being the time it takes for the asynchronous actions to run). During this time, the navigation can be interrupted with a new navigation. It can be useful to update your UI after a link/button is clicked to indicate that the next page is loading.

    You can see an example of this in the Asynchronous Navigation Example.