Bridges to JS ecosystem tooling. Separate scope from the core (src/) and internal tooling (tools/): these integrations depend on third-party APIs (bundlers, test runners, frameworks) and evolve at their own pace, independently from the framework itself.
@awacloud/fw remains dependency-free and self-contained — each integration is optional, opt-in, and pulls nothing into the application bundle beyond what the user actually consumes.
Available
| Integration | Entry | Package export | Role |
|---|---|---|---|
| Vite | integrations/vite/ |
@awacloud/fw/vite (+ @awacloud/fw/vite-env) |
Vite plugin: virtual modules virtual:@awacloud/fw/preset/* and …/side-bundle/*, sanity injection, ambient types. |
| esbuild | integrations/esbuild/ |
@awacloud/fw/esbuild |
esbuild plugin (consumer): same virtual modules via onResolve/onLoad. Node build backend: see dedicated row. |
| Rollup | integrations/rollup/ |
@awacloud/fw/rollup |
Rollup plugin (consumer): resolveId/load/transform, like Vite without the extras. |
| Bun | integrations/bun/ |
@awacloud/fw/bun |
Consumer Bun plugin (Bun.build + runtime plugin()). Distinct from the internal builder. |
| Webpack | integrations/webpack/ |
@awacloud/fw/webpack |
Webpack 5 plugin via native schemes (resolveForScheme), no dependency. |
| esbuild — backend | integrations/esbuild/backend.js |
(internal, via --backend esbuild) |
Node build backend (role 2, recommended): replaces Bun.build/Bun.gzipSync → dist/build/* under pure Node. |
| Rollup — backend | integrations/rollup/backend.js |
(internal, via --backend rollup) |
Alternative Node build backend (role 2): Rollup + terser. Heavier than esbuild. |
| Astro | integrations/astro/ |
@awacloud/fw/astro |
Astro integration: re-injects the Vite plugin via astro:config:setup; client-only sanity; SSR render.toHTML→hydrate. |
| Next.js | integrations/nextjs/ |
@awacloud/fw/next |
withFw(nextConfig) wires the Webpack plugin (or the Turbopack row below, for next dev --turbopack / Next ≥16 default); client-only sanity; SSR data. |
| Turbopack | integrations/turbopack/ |
@awacloud/fw/turbopack |
fwTurbopack(): Turbopack has no plugin API, so the adapter materializes each virtual module to a real file (.fw-virtual/ by default) and returns a resolveAlias map. Consumed by the Next.js row above. The one adapter here that is not side-effect-free at construction (it writes to disk when called) — see Bundler integration § Side-effecting modules. |
| NestJS | integrations/nestjs/ |
@awacloud/fw/nest |
FwModule.forFeature([…]): worker-safe modules as Nest providers; DOM guard (rejects fw.dom.*). Backend. |
| Vitest | integrations/vitest/ |
@awacloud/fw/vitest/shim |
Node runner: shim bun:test→vitest (bridges done + test.if), environment: 'node'. Suite intact: 8344 pass / 2 engine diffs. |
| Jest | integrations/jest/ |
@awacloud/fw/jest/shim |
Alternative Node runner: shim bun:test→@jest/globals (bridges test.if), ESM via --experimental-vm-modules. Vitest recommended. |
| TypeDoc | integrations/typedoc/ |
(script docs:api) |
HTML API reference generated from dist/types → docs/api-generated/ (separate, gitignored, outside tarball). |
| ESLint | integrations/eslint/ |
(consumed by root eslint.config.js) |
Custom rule fw/no-factory-capture (worker serialization). Other guards (no-restricted-* derived from sanity) live in eslint.config.js. |
Shared core:
integrations/_shared/core.js(internal, not exported) carries the bundler-agnostic logic — resolvesfw.config.jsonthrough the shipped pure resolver (_shared/config-resolve.js), reads the committed module catalog (_shared/catalog.generated.json), matches virtual specifiers, emits code (emit(rawId)). The default config path and anoptions.configPathoverride go through the same resolver code path (no baked-in vs live divergence). Each adapter (Vite, esbuild, …) is just a thin shell that hooks itsresolve/loadcallbacks onto this core. The generated code is therefore identical across bundlers. Because the catalog is a committed artifact,integrations/**imports onlynode:builtins + fw files — no livesrc/scan, so@awacloud/fwstays zero-runtime-dep at consume/pack time.
e2e validation:
integrations/_e2e/does real builds (esbuild/rollup/webpack/bun) of the same fixture and verifies the complete chain. The bundler/test tools are neither devDependencies nor peerDependencies (the default install stays lean): they are installed on demand viabun run setup:e2e/setup:vitest(bun add --no-save), and the runners auto-skip those that are absent.
Runtime targets (documented compat)
Node.js and Deno are not plugins but runtime targets: documented compat + browser-only boundary (dom/*, sanity) vs worker-safe. All other integrations above are delivered.
| Target | Doc | Status |
|---|---|---|
| Node.js | README · runtime DX | ✅ build (esbuild/rollup backends), tests (Vitest/Jest), consumption — all covered; example Node-native package.json provided |
| Deno | README | documented compat + smoke-test (check-deno.ts); runtime + serialized Worker validation pending a Deno env |
PC/Android packaging (Tauri/Capacitor/Electron): out of scope here. Handled in a dedicated monorepo-level folder (type
office), shared byfw,sde-coreandsdc-core— multi-target packaging is not a front integration.
Convention
- One subfolder per integration (
integrations/<name>/). - Each reads the shared source of truth —
fw.config.jsonresolved by the shipped pure resolver (_shared/config-resolve.js) plus the committed module catalog (_shared/catalog.generated.json) — rather than duplicating preset/module knowledge. Regenerate the catalog after adding/renaming fw modules:bun run integrations:catalog(verify in CI withbun run integrations:catalog:check). - No hard runtime dependency on the third-party tool: typed against a minimal structural shape (cf.
vite/index.d.tswhich does not depend on thevitepackage).
See also
- Bundler integration — standalone vs bundler-integrated.
- Per-integration HMR status — what each integration above does (or, today, does not do) with the host bundler's Hot Module Replacement channel.
docs/tools/README.md— internal tooling (build, rendering, types).