@braidlabs/angular-router
Resilient chunk recovery and version skew handling for Angular applications. Classifies lazy-route failures, probes deployment manifests, and recovers cleanly without reload loops or lost form inputs.
Installation
bash
npm install @braidlabs/angular-router @braidlabs/buildThe Problem: Stale Lazy Chunks
When a deployment lands while users are active, navigating to a lazy-loaded route throws a ChunkLoadError because the older hashed chunk was removed from the CDN. Blindly calling location.reload() can cause infinite reload loops if CDN edges or service workers are out of sync.
@braidlabs/angular-router solves this with:
- Pre-Classification Retry: Retries transient CDN misses with exponential backoff before failing.
- Manifest Probing: Probes
skew-manifest.jsonon the origin to confirm that a newer deployment actually exists before reloading. - Target Navigation Preservation: Uses
location.assign(targetUrl)rather thanlocation.reload()so the user lands on their intended destination route. - Unsaved Work Protection: Detects dirty form state and avoids interrupting active user inputs.
Setup
ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideSkewRecovery } from '@braidlabs/angular-router';
import { BUILD_ID, BUILT_AT } from './build-id'; // Generated by @braidlabs/build
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideSkewRecovery({
identity: { buildId: BUILD_ID, builtAt: BUILT_AT },
manifestUrl: '/skew-manifest.json',
maxRecoveries: 1,
respectUnsavedWork: true,
}),
],
};Wrapping Lazy Routes
Wrap your dynamic import() calls with lazy():
ts
import { Routes } from '@angular/router';
import { lazy } from '@braidlabs/angular-router';
export const routes: Routes = [
{
path: 'portfolio',
loadChildren: lazy('portfolio.routes', () => import('./portfolio/portfolio.routes')),
},
];Unsaved Work Protection
ts
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { trackUnsavedWork } from '@braidlabs/angular-router';
@Component({ ... })
export class EditorComponent {
form = new FormGroup({ title: new FormControl('') });
constructor() {
// Prevents automatic reloads while the form is dirty
trackUnsavedWork(() => this.form.dirty);
}
}