JSFiddle - React, Tailwind, and code Playground

JavaScript

class Route {
	constructor(url, controllerClass) {
  	this._url = url;
    this._controllerClass = controllerClass;
  }
  matches(currentUrl) {
  	return currentUrl.match(this._url).length > 0;
  }
  getControllerClass() {
  	return this._controllerClass;
  }
}

const Routing = {
  _routes: [],
	registerRoute(route) {
  	this._routes.push(route);
  },
  getCurrentRoute(currentUrl) {
    return this._routes.find((route) => route.matches(currentUrl));
  }
}

class Dispatcher {
	constructor() {
  	window.addEventListener('popstate', () => this.onRouteChanged());
    this.onRouteChanged();
  }
	onRouteChanged() {
  	const url = `${window.location.pathname}${window.location.hash}`;
    const route = Routing.getCurrentRoute(url);
    
    let controllerInstance = null;
    if(route) {
    	const controllerClass = route.getControllerClass();
      controllerInstance = new controllerClass();
    }
    
    const event = new Event('routeDispatched');
    event.controller = controllerInstance;
    window.dispatchEvent(event);
  }
}

class ControllerA {
	constructor() {
  	alert('It works!');
  }
}

/**
 * Initialization:
 */

Routing.registerRoute(new Route('', ControllerA));
const dispatcher = new Dispatcher();