Server-Side Routing in LWR on Node.js

You use the lwr.config.json project configuration file to set server-side routes for your app with LWR. Server-side routes can be specified in lwr.config.json by providing either:

  • a static path for each page
  • a JavaScript file that defines a hook to dynamically generate server-side routes for pages at server startup (this is an advanced option)

Both static and dynamic server-side routes can also have route handler functions, which let you customize the page response at runtime.

Read on for details. We start with a basic static routing example.

Let’s add a page to our site and do some basic (and fast!) routing.

  1. Now that you’ve got your StaticSite project, make a copy of the about.md file. Rename the new file explore.md and leave it in the content directory.
  2. Edit the explore.md file. Change the first line from # About LWR to # Explore LWR. Save the file.
  3. Open the main_layout.njk file. On a new line, add <li><a href="/explore">Explore</a> under the about line. Save the file. Code snippet showing the Explore href addition
  4. Finally, open the lwr.config.json file. Copy the entire block of code for about, including the curly brackets, and paste it below the about block. Change about to explore throughout, and don’t forget to add the comma after the closing bracket in the about block. Save the file. Code snippet showing the Explore block added
  5. If you're still in the StaticSite directory from when you first made your site, just type npm run start in the terminal to see your changes. Your updated StaticSite project runs at http://localhost:3000/, with a new Explore LWR page and a working Explore button. Screenshot of updated site with Explore LWR page

What just happened is that you:

  • created a Markdown page (explore.md) and gave it new heading text ("Explore LWR")
  • updated the site navigation in the Nunjucks layout (main_layout.njk) file to include a new Explore button
  • updated the JSON routing configuration file (lwr.config.json) to let LWR know how to route to the new page
    • you gave an id for the page (Explore)
    • you provided the path for the page (/explore)
    • you provided a contentTemplate for the page (explore.md)
    • you told LWR the layoutTemplate to use for the page; in this case, you used main_layout.njk, which is the same as for other pages in this example, though that’s not required

Static server-side routes can also have route handler functions, which let you customize the page response at runtime.

Each server-side routes object in an lwr.config.json file includes some of these properties:

  • id: The unique identifier for the route. Required.
  • path: The unique URI path from which the route is served. Required.
  • layoutTemplate: The path to a static template that renders the page layout.
  • either:
    • contentTemplate: The path to a static template that renders the page content.
    • rootComponent: The top-level Lightning web component that LWR bootstraps into the HTML output for the route. Each route must have either a rootComponent or a contentTemplate, but not both. (If you do use a rootComponent, LWR applies a default contentTemplate to render it.)
  • properties: A JSON object that can be passed to the templates as context.
  • routeHandler: A path to a route handler function configured for the route.
  • cache: The cache settings for the routing, including:
  • bootstrap: The bootstrap object contains client options that determine how an application page is loaded.
    • syntheticShadow: Set to true to turn on LWC synthetic shadow, default is false.
    • services: An array of LWC modules to run on page load.

Here’s an example of an lwr.config.json file that includes several routing properties:

You can set up routes that LWR serves if a 404 or 500 error is encountered during the bootstrap of a route. Error routes take a status code value, instead of a path value.

This is an advanced topic.

Configuration hooks update the configuration and global data for your app on server startup. You can use configuration hooks to dynamically generate server-side routes for your application.

Set the location of a configuration hook in your lwr.config.json file at the root of your project:

The following is an example of a configuration hook:

Additionally, dynamic server-side routes can use route handler functions to customize the page response at runtime.

This is an advanced topic.

Route handler functions are part of the LWR context object. They’re a server-side way to alter the current route and customize the page response. You can use route handler functions with both static and dynamic server-side routing.

Route handler functions, which are used in LWR's server-side routing, aren’t the same as route handler modules, which are used in client-side routing.

There are a couple of differences between configuration hooks and route handler functions that are worth noting:

  • A configuration hook is called once on server startup, while a route handler is triggered with each incoming page request.
  • A configuration hook applies to your entire app, whereas each route handler applies only to its specified path.

You provide the path to a route handler function in the lwr.config.json project configuration file.

A route handler function has this form:

Things to note:

  • Cache size. All the ViewDefinitionResponse.viewParams are added to the cache key for a page view response. To control cache size, monitor the number of items added.
  • Static route properties. The ViewDefinitionResponse.viewParams replace the static route properties, so if the static route properties are needed, you must merge them into the viewParams in the route handler function.
  • Markdown. The dynamic ViewDefinitionResponse.viewParams are available in Markdown content templates. This is notable because in general context isn't passed into Markdown templates, unless you use a custom route handler.
  • View. LWR merges the ViewDefinitionResponse.view with the id and bootstrap values from the current route.
  • Time-to-live. The CacheResponse.ttl is a number, in seconds, or a time string to use as the max-age on the Cache-Control header.
  • Supported languages. You can use both TypeScript and JavaScript to create your route handler.

The following is an example of using a route handler function to customize a page response. The LWR server constructs the page response from this function.

The following is an example of using a route handler function to completely override a page response. The LWR server constructs the page response from this function.