Skip to content

Example · Performance

Web Worker Layout

Layout computation is the most expensive part of a large-graph view. Move it off the main thread and your dashboard stays interactive even while the simulation is running. TopoKit ships a built-in worker layout runner — three lines of glue.

Drop-in setup

app.ts
import { create } from '@topokit/renderer-canvas';
import { workerLayoutRunner } from '@topokit/layouts/worker';

const app = create(container, {
  nodes, edges,
  layout: 'force',
  layoutRunner: workerLayoutRunner(),  // off-main-thread
});

With progress events

app.ts
const runner = workerLayoutRunner({
  tickThrottle: 8,         // post a frame every N iterations
  workerUrl: '/topokit-layout-worker.js', // optional explicit path
});

runner.on('progress', ({ iteration, alpha }) => {
  progressBar.set(iteration / 300);
});

runner.on('complete', () => {
  progressBar.hide();
});

const app = create(container, {
  nodes, edges,
  layout: 'force',
  layoutRunner: runner,
});

When to enable it

  • Graphs over ~500 nodes when you also want pan/zoom to stay smooth.
  • Force or dagre layouts (the two iterative algorithms in TopoKit).
  • Cases where you re-layout on user input (filter, expand, cluster) — the worker keeps the UI responsive between layouts.

Bundler notes

TopoKit ships topokit-layout-worker.js as a separate asset so it can be loaded by URL. Webpack, Vite, Rollup, esbuild, and Next.js all handle this automatically; if your bundler complains, copy the worker file from node_modules/@topokit/layouts/dist into your public/ and pass workerUrl.