Files
michaelschiemer/docs/modules/router.md
Michael Schiemer 36ef2a1e2c
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
fix: Gitea Traefik routing and connection pool optimization
- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
2025-11-09 14:46:15 +01:00

7.4 KiB

Router Enhancement Module

Enhanced Routing with Guards, Middleware, and Analytics

The Router Enhancement Module provides advanced routing capabilities with access control, middleware, lazy loading, and analytics.


Features

  • Route Guards - Access control for routes (auth, permissions, roles)
  • Route Middleware - Cross-cutting concerns (analytics, loading, etc.)
  • Lazy Route Loading - Load routes on demand
  • Route Analytics - Track navigation patterns
  • Integration with LiveComponents - Seamless integration with LiveComponent system
  • History & Hash Modes - Support for both history and hash routing

Quick Start

Basic Usage

import { Router, BuiltInGuards, BuiltInMiddleware } from './modules/router/index.js';

// Create router
const router = Router.create({
    mode: 'history',
    base: '/',
    enableAnalytics: true
});

// Register routes
router.routes([
    {
        path: '/',
        component: () => '<div>Home</div>',
        name: 'home',
        title: 'Home'
    },
    {
        path: '/dashboard',
        component: () => '<div>Dashboard</div>',
        name: 'dashboard',
        title: 'Dashboard',
        guards: ['auth'],
        middleware: ['analytics', 'loading']
    },
    {
        path: '/admin',
        component: () => import('./components/Admin.js'),
        name: 'admin',
        title: 'Admin',
        guards: ['auth', 'role:admin'],
        lazy: true
    }
]);

// Register guards
router.guard('auth', async (to, from) => {
    const isAuthenticated = await checkAuth();
    if (!isAuthenticated) {
        return '/login'; // Redirect to login
    }
    return true; // Allow navigation
});

// Add global middleware
router.use(BuiltInMiddleware.analytics);
router.use(BuiltInMiddleware.scrollToTop);

// Navigate
await router.navigate('/dashboard');

API Reference

Router.create(config)

Create a new Router instance.

Parameters:

  • config.mode - Routing mode: 'history' or 'hash'
  • config.base - Base path
  • config.enableAnalytics - Enable route analytics

router.route(path, config)

Register a single route.

Parameters:

  • path - Route path
  • config.component - Component (string, function, or HTMLElement)
  • config.name - Route name
  • config.title - Page title
  • config.guards - Array of guard names
  • config.middleware - Array of middleware
  • config.lazy - Lazy load component

router.guard(name, guardFn)

Register a route guard.

Parameters:

  • name - Guard name
  • guardFn - Guard function: (to, from, context) => boolean | string

router.use(middleware)

Add global middleware.

Parameters:

  • middleware - Middleware instance, function, or built-in name

router.beforeEach(hook)

Add before navigation hook.

Parameters:

  • hook - Hook function: (to, from) => boolean | string | void

router.afterEach(hook)

Add after navigation hook.

Parameters:

  • hook - Hook function: (to, from) => void

router.navigate(path, options)

Navigate to a route.

Parameters:

  • path - Route path
  • options.container - Container element
  • options.updateHistory - Update browser history

Returns: Promise<boolean>


Route Guards

Authentication Guard

router.guard('auth', async (to, from) => {
    if (!isAuthenticated()) {
        return '/login';
    }
    return true;
});

// Use in route
router.route('/dashboard', {
    component: DashboardComponent,
    guards: ['auth']
});

Role Guard

router.guard('admin', async (to, from) => {
    if (getUserRole() !== 'admin') {
        return '/unauthorized';
    }
    return true;
});

// Use in route
router.route('/admin', {
    component: AdminComponent,
    guards: ['auth', 'admin']
});

Built-in Guards

// Use built-in guards
router.route('/dashboard', {
    component: DashboardComponent,
    guards: ['auth'] // Uses BuiltInGuards.auth
});

router.route('/login', {
    component: LoginComponent,
    guards: ['guest'] // Uses BuiltInGuards.guest
});

Route Middleware

Analytics Middleware

// Use built-in analytics middleware
router.use('analytics');

// Or custom middleware
router.use(RouteMiddleware.create('custom', async (to, from, next) => {
    // Track navigation
    analytics.track('page_view', { path: to.path });
    next();
}));

Loading Middleware

router.use('loading'); // Shows loading indicator during navigation

Scroll to Top Middleware

router.use('scroll-to-top'); // Scrolls to top after navigation

Lazy Route Loading

router.route('/admin', {
    component: () => import('./components/Admin.js'),
    lazy: true
});

// Or with dynamic import
router.route('/user/:id', {
    component: async (route) => {
        const UserComponent = await import('./components/User.js');
        return UserComponent.default(route.params.id);
    },
    lazy: true
});

Integration with LiveComponents

import { Router } from './modules/router/index.js';
import { LiveComponent } from './modules/livecomponent/index.js';

const router = Router.create();

router.route('/dashboard', {
    component: async (route) => {
        // Initialize LiveComponents after navigation
        const container = document.querySelector('main');
        container.innerHTML = '<div data-live-component="dashboard"></div>';
        
        // Initialize LiveComponent
        const component = container.querySelector('[data-live-component]');
        LiveComponent.init(component);
        
        return container;
    }
});

Route Analytics

const router = Router.create({ enableAnalytics: true });

// Get analytics
const analytics = router.getAnalytics();
console.log('Total navigations:', analytics.totalNavigations);
console.log('Navigation history:', analytics.navigations);

// Listen for navigation events
window.addEventListener('router:navigation', (event) => {
    const { to, from, timestamp } = event.detail;
    console.log(`Navigated from ${from} to ${to}`);
});

Use Cases

Protected Routes

router.routes([
    {
        path: '/',
        component: HomeComponent,
        name: 'home'
    },
    {
        path: '/dashboard',
        component: DashboardComponent,
        name: 'dashboard',
        guards: ['auth']
    },
    {
        path: '/admin',
        component: AdminComponent,
        name: 'admin',
        guards: ['auth', 'admin']
    }
]);

Route with Middleware

router.route('/api-data', {
    component: ApiDataComponent,
    middleware: ['analytics', 'loading']
});

Lazy Loading

router.route('/heavy-page', {
    component: () => import('./pages/HeavyPage.js'),
    lazy: true,
    guards: ['auth']
});

Best Practices

  1. Use Guards for Access Control - Protect routes with guards
  2. Use Middleware for Cross-Cutting Concerns - Analytics, loading, etc.
  3. Lazy Load Heavy Routes - Improve initial load time
  4. Track Navigation - Use analytics to understand user behavior
  5. Handle Errors - Provide fallback routes for errors

Browser Support

  • Chrome/Edge: 90+
  • Firefox: 88+
  • Safari: 14+
  • Mobile: iOS 14+, Android Chrome 90+

Required Features:

  • ES2020 JavaScript
  • History API (for history mode)
  • Promise support

Next: Analytics Module