Understand Client-Side Routing in LWR on Node.js
With LWR’s client-side routing capabilities, you can create a Single Page Application (SPA).
For simple routing needs, LWR’s server-side routing may be all you need.
If you examine the files for your static site project, inside the
node_modules directory you find
@lwrjs/router are modules for client-side routing (
lwr/router) and navigation (
lwr/navigation). These modules export APIs to create a router, navigate, generate URLs, and subscribe to navigation events.
@lwrjs/router package is unrelated to the
routes array used in configuring server-side routes.
This page describes the concepts, architecture, and essential steps in using client-side routing with LWR.
A router is a piece of code that manages client-side navigation changes. All navigation events flow through a router for processing. You must create a router to use client-side LWR routing.
To create a router, you can either:
- use the Router Module Provider to generate a router based on a static JSON file (good for most basic use cases)
- use the
createRouter()API to create and initialize the router (for more sophisticated use cases)
This section describes the use of the Router Module Provider to create a router. “Create a Router” in Simple LWR Client-Side Routing provides an example of creating a router with the
Generate a Router with Router Module Provider
Set up Router Module Provider
Router Module Provider isn’t a default module provider, so it must be added to the project configuration. Learn more in Package and Module Configuration in LWR on Node.js.
package.json file at the root of your project, add
"@lwrjs/router/module-provider": "x.y.z" as a dependency.
In the preceding, "x.y.z" refers to the current version number. To find the current version number, examine the
Next, register the Router Module Provider in
When registering the module provider, you can optionally configure the directory location of the router JSON files.
If a configuration isn’t specified when registering the Router Module Provider, it uses this default configuration:
Configure the Router JSON
The Router Module Provider generates a router module based on JSON configuration of the type LwrRouterConfig. Example:
Import and Use the Generated Router
After you’ve specified the JSON configurations, you can import and use the generated router.
The generated router module provides a
createRouter() function that is identical to the static
createRouter() function, except that it doesn’t take a
routes array, since the routes are configured in the JSON file instead. If
caseSensitive is specified in both the JSON file and the
createRouter() call, then the
createRouter() call takes precedence.
The generated router module specifier is of the form:
@lwrjs/router/<name of the JSON config file>
A router processes incoming navigation events and uses its route definitions to determine if a location is valid. If the location is valid, the navigation event is accepted, and the browser updates the displayed content.
Locations in Navigation Events
The router receives navigation events either as URIs or page references.
- URI: A location specified in string form, as in a browser's address bar, and captured by the router via the
- Page Reference: A location specified in JSON form. You pass a PageReference object to the router via the
The router converts locations between forms. For example, the following URI and page reference are equivalent:
Route Definitions and Route Matching
A router uses route definitions to verify and process incoming location changes. A location is only valid if it can be matched to a
RouteDefinition. If given an invalid location, the application fails to navigate.
The following considerations affect whether a page reference or URI is a valid match.
Page Reference Route Matching Rules
For navigating by
pageReference, the following rules apply:
- every property specified must be defined
- literal values must be equal
- every pattern must be matched
- extra state properties are allowed
- extra attribute properties cause the match to fail
URI Route Matching Rules
When specifying query parameters in a URI, the route matches ONLY if the input URL contains the same query parameter names. For example
/path?:actionName ONLY matches if the URL contains the
actionName query key, for example:
If the query parameters provided in the URI contain a literal string for the value (e.g.,
?foo=Foo), it ONLY matches if the URL likewise contains that exact literal, e.g.,
/path?foo=Foo. This matching can be case insensitive if
caseSensitive isn’t specified in the
The order of the query parameters in the URL doesn’t matter.
Route Matching Examples
Here’s an example
RouteDefinition for a page in a recipe website:
This URI and page reference match the page’s
This URI and page reference don’t match the
When the router matches an incoming location to a
RouteDefinition, it accesses
RouteDefinition.handler to determine the associated "view". A view is the component to display when the application navigates to a location.
RouteDefinition.handler contains a Promise for your
RouteHandler module. (In LWR, modules are always provided via promises. Promises allow the module code to be lazily loaded, improving application performance.) For more on the
RouteHandler interface, see LWR Client-Side Routing Reference.
Route handler modules, which are used in client-side routing, aren’t the same as route handler functions, which are used in server-side routing.
Given information on the current location (a
RouteHandler module provides a set of views via a callback from its
Simple Client-Side Routing includes examples of additional route definition handlers, including for branching logic.
In order to use a router in an application, it must be attached to the DOM with a router container. Router containers are provided by the
A router container provides “navigation context”. This means that the router container is responsible for processing all navigation wires and events from its descendants in the DOM (
lwr-outlet in the example following).
For more information:
- “Create a Router” in Simple Client-Side Routing demonstrates attaching a router instance to a router container.
- Nested Client-Side Routing provides an example of a router container with a nested child router.
A view is the component to display when the application navigates to a location. It’s an outlet's job to dynamically render those view components. The
lwr-outlet Lightning web component uses the
CurrentView wire to get the current view component, then displays it in the DOM.
A route handler module can return multiple views. You can use multiple outlets to display all the current view components by setting different
lwr-outlet in LWR Client-Side Routing Reference provides more details on using the
@lwrjs/router package provides an implementation of
lightning/navigation module is an alias for the
lwr/navigation module, so it includes the same wires and APIs, along with
NavigationMixin. This allows you to write a component once and use it anywhere that supports the