DEV Community 👩‍💻👨‍💻

DEV Community 👩‍💻👨‍💻 is a community of 967,611 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for How to add Simplr Router to the open-wc starter app
Matsuuu
Matsuuu

Posted on

How to add Simplr Router to the open-wc starter app

The Open-WC starter is one of the best ways to get started writing web component applications. It provides a simple base project initialized with everything you need to start writing web components.

However in the case you might want to be creating a SPA application from the starter, you will be needing a client-side router to handle your page history, load views and
handle transitions between them.

In this tutorial we'll go through the setup of creating a open-wc project, and attaching Simplr Router to it.

Initial setup

We'll start by initializing our project with the @open-wc starter.

npm init @open-wc
Enter fullscreen mode Exit fullscreen mode

This will prompt you to generate a starter application for your web component project. You should choose to create an application, and add whatever optional tooling you need.

The setup we're using in this tutorial is as follows:

✔ What would you like to do today? › Scaffold a new project
✔ What would you like to scaffold? › Application
✔ What would you like to add? ›
✔ Would you like to use typescript? › No
✔ What is the tag name of your application/web component? … simplr-router-demo
Enter fullscreen mode Exit fullscreen mode

With these settings, you should have a JavaSript based project ready for development.

Next we'll add the router.

Installing the router

Simplr router can be installed through npm. The package has no dependencies so the footprint it will add on your project isn't going to be anything you need to worry about.

npm install @simplr-wc/router
Enter fullscreen mode Exit fullscreen mode

Configuring the Dev server

Like with most client-side routers, to provide the best user experience we need to enable the History API fallback for our dev server. This will make it so that if the user loads any other page than the front page of our application, they will still be shown the index file of our project, in which our router resides.

The Web Dev Server has an easy configuration for that.

Open up the web-dev-server.config.mjs -file and modify the appIndex field.

// import { hmrPlugin, presets } from '@open-wc/dev-server-hmr';

/** Use Hot Module replacement by adding --hmr to the start command */
const hmr = process.argv.includes('--hmr');

export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
  open: '/',
  watch: !hmr,
  /** Resolve bare module imports */
  nodeResolve: {
    exportConditions: ['browser', 'development'],
  },

  /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
  // esbuildTarget: 'auto'

  /** Set appIndex to enable SPA routing */
  appIndex: 'index.html',

  plugins: [
    /** Use Hot Module Replacement by uncommenting. Requires @open-wc/dev-server-hmr plugin */
    // hmr && hmrPlugin({ exclude: ['**/*/node_modules/**/*'], presets: [presets.litElement] }),
  ],

  // See documentation for all available options
});
Enter fullscreen mode Exit fullscreen mode

Now we're all set up and can start developing!

Instantiating the router

Let's start by removing the main web component from our index.html -file since we want our router to take control of displaying views on the page.

<!-- index.html -->
<body>
  <script type="module" src="./src/simplr-router-demo.js"></script>
</body>
Enter fullscreen mode Exit fullscreen mode

Then we'll move on to modifying the file loaded by our index.html. In this case that file is named simplr-router-demo.js

Let's first initialize the routing for our first view:

const routes = [
    { path: "", component: "simplr-router-demo" }
];
Enter fullscreen mode Exit fullscreen mode

Then let's create an instance of Simplr Router and pass it the routes as options:

const router = new SimplrRouter({ routes });
Enter fullscreen mode Exit fullscreen mode

And finally initialize the router (this will start the routing process).

router.init();
Enter fullscreen mode Exit fullscreen mode

The file should looks something along the lines of this by now:

import { SimplrRouter } from "@simplr-wc/router";
import { SimplrRouterDemo } from "./SimplrRouterDemo.js";

customElements.define("simplr-router-demo", SimplrRouterDemo);

const routes = [
    { path: "", component: "simplr-router-demo" }
];

const router = new SimplrRouter({ routes });
router.init();
Enter fullscreen mode Exit fullscreen mode

The starting view should now be visible on your browser.

Adding views

Next we will want to do some actual routing. This requires a few steps:

  1. Create a view to navigate to
  2. Add it as a route
  3. Create a link to navigate to the page

Create a view to navigate to

Let's create a new view into our src folder as a new file called ExampleView.js.

import { LitElement, html } from "lit";

export class ExampleView extends LitElement {
    render() {
        return html`
      <p>Hello from the example view!</p>
      <a href="/">Please take me back!</a>
    `;
    }
}

customElements.define("example-view", ExampleView);
Enter fullscreen mode Exit fullscreen mode

Add it as a route

Next you'll have to add this new view as a route. Navigate to the file with our routes, and add it there.

import { SimplrRouter } from "@simplr-wc/router";
import { SimplrRouterDemo } from "./SimplrRouterDemo.js";
import "./ExampleView.js";

customElements.define("simplr-router-demo", SimplrRouterDemo);

const routes = [
    { path: "", component: "simplr-router-demo" },
    { path: "example", component: "example-view" } // New route
];

const router = new SimplrRouter({ routes });
router.init();
Enter fullscreen mode Exit fullscreen mode

To have our custom element view registered, we need to import our ExampleView.js -file so that the customElement defininition is run.

To increase performance and decrease the initial load, we could also apply lazy loading to our routes.

To do that, we need to apply a import property to our route.

const routes = [
    { path: "", component: "simplr-router-demo" },
    // Move the import from top of the file to here
    { path: "example", component: "example-view", import: () => import("./ExampleView.js") }
];
Enter fullscreen mode Exit fullscreen mode

Create a link to navigate to the page

Lastly you'll need a way to navigate to the page. This is where Simplr Router differs from some other routing libraries: You'll do it the same way you'd do it with a Multi Page Application:

Add a anchor tag pointing to the new page into the starting view:

// SimplrRouterDemo.js
// Some code omitted for clarity
render() {
    return html`
      <main>
        <div class="logo"><img alt="open-wc logo" src=${logo} /></div>
        <h1>${this.title}</h1>
        <a href="/example">Take me to the example page!</a>
      </main>
    `;
}
Enter fullscreen mode Exit fullscreen mode

After doing this, you should be able to navigate between the pages seamlessly!

You can even use the browser's navigation buttons to navigate between these views.


More advanced recipes

This was just a small dive into how to setup a project with Simplr Router, but the router is capable of much more.

Some examples of it's capabilities will be listed below, and a broader collection can be found in the documentation site.

Dynamic routing

Many web applications will end up with situations where dynamic routes are needed. An example of this would be a "Get user by ID" -view.

With Simplr Router dynamic routing can be executed easily.

const routes = [
    { path: "", component: "front-page" },
    { path: "user", component: "user-list" },
    // Dynamic route
    { path: "user/:id", component: "user-profile" },
];
Enter fullscreen mode Exit fullscreen mode

As the user navigates to e.g. /user/555, the property 555 will be bound to the id property of the view.

Pattern matching dynamic routes

Sometime you might want to limit the matching range of your dynamic routes. For these situations you can apply pattern matching per parameter for your routes.

const routes = [
    { path: "", component: "minimal-setup" },
    {
        path: "onlynumbers/:id",
        pattern: {
            // Matches routes with numbers as the :id
            // /onlynumbers/123
            // /onlynumbers/555
            id: "[0-9]+"
        },
        component: "dynamic-view"
    },
    {
        path: "onlynumbers/:id/thenword/:specialType",
        pattern: {
            id: "[0-9]+",

            // Matches routes with one of the matched words
            // /onlynumbers/123/thenword/foo
            // /onlynumbers/123/thenword/bar
            // /onlynumbers/123/thenword/baz
            specialType: "(foo|bar|baz)"
        },
        component: "dynamic-view"
    },
];
Enter fullscreen mode Exit fullscreen mode

Adding transitions

You can create transition animations for your views by modifying the css of the wrapper Simplr Router creates.

To enable transitions, a transitionSpeed property needs to be set in the config.

To enable transitions, a transitionSpeed property needs to be set in the config.

const routerOptions = {
    routes: [
        {
            name: "Home",
            path: "",
            component: "router-demo",
        },
        {
            name: "Example",
            path: "example",
            component: "router-example",
        }
    ]
    transitionSpeed: 400 // in ms
}

const router = new SimplrRouter(routerOptions);
router.init();
Enter fullscreen mode Exit fullscreen mode

Now all that is needed is to modify the css of the simplr-router-container -element.

For example if we wanted to apply a "fade in and out" effect to our transitions, we could easily implement that with CSS now.

simplr-router-container[entering-view],
simplr-router-container[leaving-view] {
  opacity: 0;
}
Enter fullscreen mode Exit fullscreen mode

The entering-view and leaving-view attributes are added to the view wrappers as they are entering and leaving the view. By modifying the styling of these two selectors, you can create all kinds of transitions on your web app.

More example of transitions can be found here

Using an outlet

Simplr Router creates a container for your views that fills the whole screen by default.

In some cases you might want to only have a part of the page change instead of the whole content.

In these cases an outlet can be used to determine the area in which content changes.

Determining an outlet is done by creating a simplr-router-outlet somewhere on your web page.

render() {}
  return html`<main>
    <div class="logo"><img alt="open-wc logo" src=${logo} /></div>
    <simplr-router-outlet></simplr-router-outlet>
  </main>
  `;
}
Enter fullscreen mode Exit fullscreen mode

After the outlet has been added, Simplr Router will look for a outlet when navigating. If one is found, it is used instead of the default behavior.

Closing words

In this lengthy post we went through how you could setup a routing solution for your open-wc starter project with Simplr Router. I hope this was useful and gets your started in creating more feature rich, web component based applications.


You can find the full documentation and more guides in the official docs at https://simplr.github.io/simplr-router/

Top comments (0)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.