Guide · @staticflux/vite-plugin · @staticflux/rspack-plugin · @staticflux/sf · @staticflux/loader

Build tooling: Vite, Rspack & the sf CLI

Packages are bundler-agnostic plain ESM. The only build contract is the loader’s sf-manifest/1; the plugins produce it, and the CLI keeps everyone honest.

Vite 8 (default)

vite.config.ts
import { defineConfig } from 'vite';
import { staticflux } from '@staticflux/vite-plugin';
import { chunkDeclarations } from './src/app/chunks.js';

export default defineConfig({
  plugins: [staticflux({
    chunks: chunkDeclarations,
    bootEntries: ['src/boot-browser.ts'],
    budgets: { onViolation: process.env.CI ? 'error' : 'warn', bootKb: 150 },
    isolation: 'preferred', coep: 'credentialless',
  })],
});

Each declaration with an entry becomes a stable, readable chunk (assets/feature.studio-desktop-<hash>.js). The plugin emits sf-manifest.json, sf-preloads.json (per profile), sf-precache.json (critical tier, Workbox format) and sf-build-report.json, injects boot-plan modulepreload tags, serves COOP / COEP / CORP in dev and preview, and checks chunk, eager and boot budgets. App code imports chunks by logical id through virtual:sf-chunks.

TypeScript
import { chunks } from 'virtual:sf-chunks';
defineFeature({ id: 'studio/desktop', weight: 'heavy', modes: ['expanded'],
  load: () => chunks['feature:studio-desktop']!() as Promise<FeatureModule> });

Rspack + Module Federation 2.0

staticfluxRspack(options) emits the same files from the compilation’s chunk groups for organizations deploying independently. It maps remotes’ exposed modules to logical chunk ids and validates host-owned shared singletons and versions at build time (P9: one version per app); the loader re-checks the ranges before a remote’s init. Any other bundler works by producing the same manifest with createManifest from @staticflux/loader.

The sf CLI

CommandWhat it checks
sf graph <entry>DI graph: cycles, scope rules, fan-in / fan-out, duplicate and unused providers, boot order, critical set
sf lintno-direct-flag-reads, no-bare-listener, inheritance-depth, no-string-tokens, no-default-export
sf errorsCollects every defineError into docs/errors.json; --check fails on stale or conflicting codes
sf budgetsLimit vs actual; proposes tightening (ratchet), never loosens
sf agentsRegenerates the “Budgets” and “Allowed dependencies” sections of every AGENTS.md
sf routes <entry>Route × profile completeness: every capability-bound route has a feature for every mode
sf manifest <file>Validates an sf-manifest.json: shapes, dangling deps, budgets, eager reasons
Shell
pnpm lint:sf            # sf lint over packages/*/src
pnpm errors:check       # catalog is current
pnpm budgets            # size-limit --json → sf budgets (ratchet proposals)
pnpm agents:check       # generated AGENTS.md sections are current
pnpm sf graph dist/units.js --max-fan-out 12    # any module exporting `units`

AGENTS.md on GitHub: @staticflux/vite-plugin · @staticflux/rspack-plugin · @staticflux/sf · @staticflux/loader