npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

router-for-dom

v1.1.0

Published

Routing library for DOM.

Downloads

1

Readme

Router for dom.

This library uses webpack. I added my webpack config to the project. You can learn more here.

If you like this project please show your support with a GitHub :star:!

Introduction.

router-for-dom - It is a routing library for JavaScript in the browser. Includes the following Features:

  • Automatic placement and removal of active CSS class for links.
  • Dynamic Route Matching.
  • HTML5 history mode.
  • Lazy Loading Routes.

Installation.

Npm

npm i router-for-dom

Yarn

yarn add router-for-dom

Getting Started.

HTML

<div id="app">
  <header class="header">
    <nav class="header-navigation">
      <div class="header-navigation__wrapper-content">
        <ul class="header-navigation__content">
          <li class="header-navigation__item">
            <!-- We Use the 'data-router-link' attribute to tell the router that this is a navigation link. -->
            <!-- When the url is '/' then an 'active-class' will be added for all html elements that have this attribute. -->
            <a data-router-link="/" class="header-navigation__link"> Home </a>
          </li>

          <li class="header-navigation__item">
            <!-- We Use the 'data-router-link' attribute to tell the router that this is a navigation link -->
            <!-- When the url is '/Contact' then an 'active-class' will be added for all html elements that have this attribute. -->
            <a data-router-link="/Contact" class="header-navigation__link"> Contact </a>
          </li>

          <li class="header-navigation__item">
            <!-- We Use the 'data-router-link' attribute to tell the router that this is a navigation link -->
            <!-- When the url is '/Contact' then an 'active-class' will be added for all html elements that have this attribute. -->
            <a data-router-link="/About-me" class="header-navigation__link"> About me </a>
          </li>
        </ul>
      </div>
    </nav>
  </header>
</div>

TYPESCRIPT

// 1) We importing the router class.
import { Router, IRouter } from 'router-for-dom';

// 2) We are importing the pages we want to use.
import { Contact, AboutMe, Home } from 'src/pages';

// 3) We create an instance of the router class and pass parameters to it.
const router: IRouter = new Router({
  // Should be the html element on which the pages will be rendered.
  el: document.querySelector('#app') as HTMLElement,

  // Passing the pages that we want to use.
  routes: [
    {
      path: '/',
      page: Home,
    },
    {
      path: '/About-me',
      page: AboutMe,
    },
    {
      path: '/Contact',
      page: Contact,
      // optional fields.
      state: {
        email: '[email protected]',
      },
    },
  ],
});

PAGES

// src/pages/Home.ts
import { IPage, IPageParams } from 'router-for-dom';

export class Home implements IPage {
  constructor(private params: IPageParams) {
    this.init();
  }

  private init(): void {
    console.log('home: params', this.params); // { router: IRouter -> router class instance, stateHistory: {} }
  }

  // the router will call this method to get the page content.
  public toHtml(): HTMLElement {
    const element = document.createElement('h1');
    element.textContent = 'Home page';
    return element;
  }

  // hooks

  // This hook will fire before changing the content of the html element.
  public beforeRenderElement(): void {
    console.log('home: beforeRenderElement');
  }

  // This hook will fire after changing content of html element.
  public afterRenderElement(): void {
    console.log('home: afterRenderElement');
  }
  
  // This hook will fire after push method has been called.
  public destroy(): void {
    console.log('home: destroy');
  }
}
// src/pages/AboutMe.ts
import { IPage, IPageParams } from 'router-for-dom';

export class AboutMe implements IPage {
  constructor(private params: IPageParams) {
    this.init();
  }

  private init(): void {
    console.log('about-me: params', this.params); // { router: IRouter -> router class instance, stateHistory: {} }
  }

  // the router will call this method to get the page content.
  public toHtml(): HTMLElement {
    const element = document.createElement('h1');
    element.textContent = 'About-me page';
    return element;
  }

  // hooks

  // This hook will fire before changing the content of the html element.
  public beforeRenderElement(): void {
    console.log('about-me: beforeRenderElement');
  }

  // This hook will fire after changing content of html element.
  public afterRenderElement(): void {
    console.log('about-me: afterRenderElement');
  }
  
  // This hook will fire after push method has been called.
  public destroy(): void {
    console.log('about-me: destroy');
  }
}
// src/pages/Contact.ts
import { IPage, IPageParams } from 'router-for-dom';

export class Contact implements IPage {
  constructor(private params: IPageParams) {
    this.init();
  }

  private init(): void {
    console.log('contact: params', this.params);
    /**
     * {
     *   router: IRouter -> router class instance,
     *   stateHistory: { email: '[email protected]' }
     * }
     */
  }

  // the router will call this method to get the page content.
  public toHtml(): HTMLElement {
    const element = document.createElement('div');
    element.insertAdjacentHTML(
      'afterbegin',
      `
      <h1>Contact page</h1>
      <ul>
        <li>Email: ${this.params.stateHistory.email}</li>
      </ul>
    `,
    );
    return element;
  }

  // hooks

  // This hook will fire before changing the content of the html element.
  public beforeRenderElement(): void {
    console.log('contact: beforeRenderElement');
  }
  

  // This hook will fire after changing content of html element.
  public afterRenderElement(): void {
    console.log('contact: afterRenderElement');
  }

  // This hook will fire after push method has been called.
  public destroy(): void {
    console.log('contact: destroy');
  }
}
// src/pages/index.ts
export { AboutMe } from './AboutMe';
export { Contact } from './Contact';
export { Home } from './Home';

Dynamic Route Matching

Very often we need to match routes to a given pattern. For example, we might have a user page that should be displayed to all users, but with different user IDs. In router-for-dom, we can use a dynamic segment in the route to achieve this:

// 1) We importing the router class.
import { Router, IRouter } from 'router-for-dom';

// 2) We are importing the pages we want to use.
import { User } from 'src/pages';

// 3) We create an instance of the router class and pass parameters to it.
const router: IRouter = new Router({
  // Should be the html element on which the pages will be rendered.
  el: document.querySelector('#app') as HTMLElement,

  // Passing the pages that we want to use.
  routes: [
   {
      path: '/user/:id',
      page: User,
    },
  ],
});
// src/pages/User.ts
import { IPage, IPageParams } from 'router-for-dom';

export class User implements IPage {
  constructor(private params: IPageParams) {
    this.init();
  }

  private init(): void {
    console.log('user: params', this.params);
    /**
     * {
     *   router: IRouter -> router class instance,
     *   stateHistory: { Id: dynamic }
     * }
     */
  }

  // the router will call this method to get the page content.
  public toHtml(): HTMLElement {
    const element = document.createElement('div');
    element.insertAdjacentHTML(
      'afterbegin',
      `
      <h1>User page</h1>
      <ul>
        <li>Id: ${this.params.stateHistory.id}</li>
      </ul>
    `,
    );
    return element;
  }

  // hooks

  // This hook will fire before changing the content of the html element.
  public beforeRenderElement(): void {
    console.log('user: beforeRenderElement');
  }

  // This hook will fire after changing content of html element.
  public afterRenderElement(): void {
    console.log('user: afterRenderElement');
  }

  // This hook will fire after push method has been called.
  public destroy(): void {
    console.log('user: destroy');
  }
}

Now URLs like /user/foo and /user/bar will both map to the same route.

Lazy Loading Routes.

When using a modular system, the resulting JavaScript assembly can be quite large, which negatively affects page load time. In some cases, it would be more efficient to split the pages into separate fragments and load them only when going to the corresponding route.

// 1) We importing the router class.
import { Router, IRouter } from 'router-for-dom';

// 2) We are importing the pages we want to use.
import { Contact, AboutMe, Home } from 'src/pages';

// 3) We create an instance of the router class and pass parameters to it.
const router: IRouter = new Router({
  // Should be the html element on which the pages will be rendered.
  el: document.querySelector('#app') as HTMLElement,

  // Passing the pages that we want to use.
  routes: [
    {
      path: '/',
      page: () => import('src/pages/Home').then((res) => res.Home),
    },
    {
      path: '/About-me',
      page: () => import('src/pages/AboutMe').then((res) => res.AboutMe),
    },
    {
      path: '/Contact',
      page: () => import('src/pages/Contact').then((res) => res.Contact),
      // optional fields.
      state: {
        email: '[email protected]',
      },
    },
    {
      path: '/user/:id',
      page: () => import('src/pages/User').then((res) => res.User),
    },
  ],
});

Router (API)

push - To navigate to a different URL, use router.push.

  • @param{string} path - Url address to go to a new page.
// 1) We importing the router class.
import { Router, IRouter } from 'router-for-dom';

// 2) We are importing the pages we want to use.
import { Contact, AboutMe, Home } from 'src/pages';

// 3) We create an instance of the router class and pass parameters to it.
const router: IRouter = new Router({
  // Should be the html element on which the pages will be rendered.
  el: document.querySelector('#app') as HTMLElement,

  // Passing the pages that we want to use.
  routes: [
    {
      path: '/',
      page: () => import('src/pages/Home').then((res) => res.Home),
    },
    {
      path: '/About-me',
      page: () => import('src/pages/AboutMe').then((res) => res.AboutMe),
    },
    {
      path: '/Contact',
      page: () => import('src/pages/Contact').then((res) => res.Contact),
      // optional fields.
      state: {
        email: '[email protected]',
      },
    },
    {
      path: '/user/:id',
      page: () => import('src/pages/User').then((res) => res.User),
    },
  ],
});

router.push('/About-me');

getStateHistory - This method returns the states of the browser history.

  • @returns {Object} - history state
// 1) We importing the router class.
import { Router, IRouter } from 'router-for-dom';

// 2) We are importing the pages we want to use.
import { Contact, AboutMe, Home } from 'src/pages';

// 3) We create an instance of the router class and pass parameters to it.
const router: IRouter = new Router({
  // Should be the html element on which the pages will be rendered.
  el: document.querySelector('#app') as HTMLElement,

  // Passing the pages that we want to use.
  routes: [
    {
      path: '/',
      page: () => import('src/pages/Home').then((res) => res.Home),
    },
    {
      path: '/About-me',
      page: () => import('src/pages/AboutMe').then((res) => res.AboutMe),
    },
    {
      path: '/Contact',
      page: () => import('src/pages/Contact').then((res) => res.Contact),
      // optional fields.
      state: {
        email: '[email protected]',
      },
    },
    {
      path: '/user/:id',
      page: () => import('src/pages/User').then((res) => res.User),
    },
  ],
});

console.log(router.getStateHistory()) // Object