Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b04b463
ScriptedAlchemy Sep 7, 2026
c38c4c0
chore: remove accidental empty file
ScriptedAlchemy Sep 7, 2026
7ecde91
perf(website): reduce first-screen JavaScript (#5064)
2heal1 Sep 14, 2026
d6bb5a6
chore(deps-dev): bump js-yaml from 4.3.1 to 4.3.2 (#5069)
dependabot[bot] Sep 16, 2026
35f2119
feat(devtools): add WebMCP, browser builds and release downloads (#5106)
2heal1 Sep 21, 2026
07a2157
chore: release v2.9.1 (#5108)
2heal1 Sep 21, 2026
4364cb6
fix(bridge-react): deduplicate lazy component loading (#5092)
2heal1 Sep 22, 2026
000f3fa
chore(deps): upgrades `adm-zip` to `0.6.1` (#5103)
deiga Sep 23, 2026
936cade
docs(skills): add sokra-mode skill for webpack plugin architecture (#…
ScriptedAlchemy Sep 24, 2026
23c5a9f
chore(deps-dev): bump eslint-plugin-import from 2.31.0 to 2.32.0 (#5017)
dependabot[bot] Sep 25, 2026
6bd7ea0
chore(deps-dev): bump eslint-plugin-prettier from 5.2.1 to 5.5.6 (#5020)
dependabot[bot] Sep 25, 2026
a7ce90d
chore(deps): bump react-router-dom from 6.30.3 to 6.30.6 in /apps/rou…
dependabot[bot] Sep 25, 2026
5bafdde
chore(deps): bump hono from 4.13.1 to 4.13.5 (#5043)
dependabot[bot] Sep 25, 2026
e5820a4
chore(deps): bump sharp from 0.35.0 to 0.35.4 (#5057)
dependabot[bot] Sep 25, 2026
1880a2b
chore(deps-dev): bump vitest from 3.2.6 to 4.1.11 (#5056)
dependabot[bot] Sep 25, 2026
47d9b46
fix(runtime-core): import ResourceLoadContext in the remote handler (…
ScriptedAlchemy Sep 25, 2026
c130946
fix(enhanced): report a missing expose as a build error instead of ex…
ScriptedAlchemy Sep 25, 2026
923b55d
fix(enhanced): wait for addEntry in SharedContainerPlugin make (#5122)
ScriptedAlchemy Sep 25, 2026
412f62e
fix(enhanced): restore missing expose diagnostics (#5146)
ScriptedAlchemy Sep 25, 2026
2b205dc
chore(deps): move the repo to @rspack/core 2 (#5126)
ScriptedAlchemy Sep 26, 2026
1b4ff2e
fix(esbuild): resolve paths from absWorkingDir instead of process.cwd…
ScriptedAlchemy Sep 26, 2026
7f0ac8b
fix(deps): upgrade undici to 7.29.1 (#5150)
ScriptedAlchemy Sep 26, 2026
a34a045
chore: release v2.9.2 (#5153)
ScriptedAlchemy Sep 26, 2026
d457532
docs(skills): expose sokra mode to Codex (#5166)
ScriptedAlchemy Sep 29, 2026
edf1219
fix(enhanced): skip inactive connections when hoisting runtime module…
ScriptedAlchemy Sep 29, 2026
020fa27
fix(enhanced): sort remote modules in runtime mappings (#5115)
ScriptedAlchemy Sep 29, 2026
ee32a0d
fix(enhanced): keep distinct requiredVersion ranges as distinct consu…
ScriptedAlchemy Sep 29, 2026
83a0640
fix(runtime-core): fall back when runtime-infer share coverage misses
tonoizer Sep 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .agents/skills/sokra-mode/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: sokra-mode
description: >-
Apply sokra's webpack design discipline to module-federation/core plugin
architecture, runtime, caching, and reviews when asked for sokra mode or
to review or build something like sokra would.
---

# Sokra mode for Codex

Read and follow the repository's [shared Sokra-mode guidance](../../../.claude/skills/sokra-mode/SKILL.md) before working on the requested task. That file is the source of truth for both Claude and Codex; keep architecture, verification, and review guidance there.

Resolve the shared skill's relative reference links from its own directory, `.claude/skills/sokra-mode/`. Read its plugin patterns and repository map when the shared guidance calls for them.

Invoke this skill with `$sokra-mode`. Preserve the existing opt-in behavior through `agents/openai.yaml`; the shared skill's `disable-model-invocation` frontmatter is Claude metadata, not Codex configuration.
2 changes: 2 additions & 0 deletions .agents/skills/sokra-mode/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
policy:
allow_implicit_invocation: false
7 changes: 7 additions & 0 deletions .changeset/consume-shared-distinct-ranges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@module-federation/enhanced': patch
---

Keep one consume-shared module per `requiredVersion` range. Two packages that
require different ranges of the same shared dependency no longer collapse into
one module, so each gets its own version check.
5 changes: 5 additions & 0 deletions .changeset/hoist-inactive-connections.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@module-federation/enhanced': patch
---

HoistContainerReferencesPlugin no longer hoists modules that webpack already pruned. The module graph walk now skips connections whose active state is false, such as an unused import of a `sideEffects: false` package, so the runtime chunk keeps only modules that are reachable through an active connection.
6 changes: 6 additions & 0 deletions .changeset/runtime-infer-share-coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@module-federation/runtime-core': patch
'@module-federation/webpack-bundler-runtime': patch
---

Fall back to the full shared getter when a `runtime-infer` tree-shaken variant does not cover the consumer's used exports.
5 changes: 0 additions & 5 deletions .changeset/salty-deer-cheat.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/secure-websocket-client.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/stable-remote-runtime-order.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@module-federation/enhanced": patch
---

Fix remote runtime output ordering for stable build hashes.
5 changes: 0 additions & 5 deletions .changeset/wise-corners-care.md

This file was deleted.

86 changes: 86 additions & 0 deletions .claude/skills/sokra-mode/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
name: sokra-mode
description: >-
Design, build, and maintain module-federation/core the way sokra (Tobias
Koppers) built webpack 5: plugin architecture, container/sharing, runtime,
caching, and reviews. Use for /sokra-mode, "sokra mode", "do it like sokra",
or "review this like sokra would".
disable-model-invocation: true
---

# sokra mode

This skill applies sokra's webpack design discipline to building and maintaining this repo. `packages/enhanced` is a TypeScript fork of the container and sharing plugins he wrote, so his rules apply there directly. The rules come from his public webpack/webpack record: 739 authored PRs and 717 reviews (2019–2022), and 400 issues plus 49 discussions (2020–2024). His webpack code stops in November 2022. Don't impersonate him: never sign as him, post as him, or claim his approval. Detailed patterns with evidence links are in [references/plugin-patterns.md](references/plugin-patterns.md), and the per-package map of this repo's thirteen plugin packages is in [references/repo-map.md](references/repo-map.md). Read both before writing a new plugin, Module, Dependency, RuntimeModule, or runtime hook.

## Architecture

- **Build one feature as a slice of small classes.** Each class has one job and its own file: Plugin (wiring), Dependency plus Template, Module subclass, ModuleFactory, RuntimeModule, and a `RuntimeGlobals` entry.
- **Umbrella plugins only compose.** `ModuleFederationPlugin` → `ContainerPlugin` + `ContainerReferencePlugin` + `SharePlugin` → `ConsumeSharedPlugin` / `ProvideSharedPlugin`.
- **Reuse existing machinery.** Remotes are externals. A container is a normal entry with a `library`. Fallbacks go through `normalModuleFactory`.
- **Connect parts through hooks and requirements, not direct calls.**
- Code declares `runtimeRequirements`, and `runtimeRequirementInTree` adds the modules they need.
- Extension points are `static getCompilationHooks(compilation)` backed by a `WeakMap`. `FederationModulesPlugin` is this repo's example.
- **Put logic where the concern lives.** Loading goes in the loading or runtime plugin. Error text goes in the error. Build-phase work goes in `Module.build`.
- **Keep build and codeGeneration apart.** Never mutate `buildInfo` in codegen. Pass data out through codegen `data` and custom source types. Anything that crosses from build to codegen must be serializable.
- **Keep the core small, and challenge the premise first.**
- Ask for the use case, and check whether an existing option or hook already covers it.
- For rare needs, expose a small override or a replaceable module, not new config.
- Never add globals.
- Don't branch on `target`; gate on environment or feature flags.

## Discipline

- **Builds must be deterministic.** Sort every emitted map and key, and use tiebreakers. Output must not depend on build order, the machine, or the Node version. Adding a chunk must not rewrite shared chunks.
- **Caching must be correct by default.**
- Cached classes use `makeSerializable` and serialize every field, including subclass fields.
- Per-compilation state goes in a `WeakMap`.
- Dependency paths are absolute.
- Anything unsafe stays opt-in.
- **Performance is a correctness concern.** Hot paths do one `get` and compare to `undefined`. Avoid throwaway arrays and quadratic scans. Hoist constant `Set`s and comparators. Lazy-require with `memoize`. Measure perf claims.
- **Memory-trading optimizations are not plain wins.** A cache that grows, or that keeps modules which have left the compilation, goes behind `experiments.*` with eviction, or gets reverted ([#14436](https://github.com/webpack/webpack/pull/14436), [#14319](https://github.com/webpack/webpack/pull/14319)).
- **Never break a public or plugin-facing interface in a minor.** New behavior ships behind `experiments.*`. Renames keep a deprecation shim.
- **Report problems as errors when the output can't be correct, otherwise as warnings.** Messages name the cause and the fix.
- **Every option gets a schema and a precise type.** Name options positively. Use the graph APIs (`moduleGraph`, `chunkGraph`), never legacy `module.*` fields. Use `RuntimeGlobals` and `runtimeTemplate.basicFunction`/`returningFunction`, never a literal `__webpack_require__.x`.

## This repo

- **Package roles.** Thirteen packages are bundler plugins; [references/repo-map.md](references/repo-map.md) lists each with its hooks and gaps.
- `enhanced` is the webpack plugin layer, and every rule above applies in full.
- `node`, `nextjs-mf`, `dts-plugin`, `manifest`, `utilities`, and the legacy plugins compose on top of it. Same rules: umbrella plugins compose, runtime goes through requirements, assets go through `processAssets` with a named stage, options are validated at the boundary.
- `rspack` and `rsbuild-plugin` wrap rspack's native MF plugin. They shape options; module and dependency internals live in rspack itself.
- `runtime-core` and `webpack-bundler-runtime` hold the runtime logic.
- `sdk` owns the shared option types.
- **Runtime split.** RuntimeModules in `enhanced` stay thin: they emit data (mappings, ids) and call `federationGlobal.bundlerRuntime.*`. Logic lives in `runtime-core` or `webpack-bundler-runtime`, with unit tests there. This is a deliberate MF 2 change to sokra's "generate the runtime" rule. His rules still govern the glue: `RuntimeGlobals`, requirements, and template helpers.
- **Extend at runtime through plugins.** Keep `runtime-core` small. Add a hook in its plugin system (`src/utils/hooks`) or a runtime plugin (`runtime-plugins`, `retry-plugin`) before adding an option.
- **Webpack internals.**
- Load them through `normalizeWebpackPath` (see `AGENTS.md`).
- `makeSerializable` keys are `'enhanced/lib/<path>'`, and there is no `internalSerializables` registry.
- Types are TypeScript. Avoid `any` and unchecked casts where a precise type exists.
- **Options.** Types go in `packages/sdk/src/types/plugins/ModuleFederationPlugin.ts` and schemas in `packages/enhanced/src/schemas`. Then run `pnpm --filter @module-federation/enhanced run generate:schema`; the pre-commit hook also runs it when schema JSON changes. New behavior goes under the plugin's `experiments`.
- **Errors.** Runtime errors carry codes from `@module-federation/error-codes`, which is this repo's equivalent of `DEP_WEBPACK_*`. Build problems go to `compilation.errors` or `compilation.warnings`.
- **Compatibility.** Every package is published. Add a changeset (`pnpm run changeset`) for publishable behavior changes.

## Verification

- **Every fix and feature needs a regression test that hits the edge that broke.**
- Build-side: `packages/enhanced/test/configCases/<area>/<case>`, or `test/compiler-unit`. Other plugin packages use jest or rstest cases next to the source.
- Runtime: `packages/runtime-core/__tests__/*.spec.ts`.
- E2E: the matching app in `apps/`, via `pnpm run ci:local --only=<job>`.
- Run with `pnpm --filter <pkg> run test`.
- A PR without a test is blocked.
- **When you fix one path, check its siblings.** Grep every path that emits the same thing. Check the counterparts in `rspack`, `runtime-core`, `webpack-bundler-runtime`, `node`, and `nextjs-mf` too.
- **Regenerate derived files in the same change:** snapshots, types, schema outputs.

## Reviews

- **Approve without comment, and put every objection inline.** Prefer a `suggestion` block to a description.
- **Lead with the verdict** ("working as expected", "that's a bug", "not supported"). Then give the mechanism in one or two sentences, then a snippet or a permalink.
- **Keep requests short and imperative:** "Please add a test case", "Use `X` instead". When refusing, give the reason and name the alternative. Reject refactors that bring no concrete benefit.
- **Push guards back to the root cause.** "This should never be undefined" means find where the value is produced.
- **Triage:** get a minimal repro repo before debugging, and profiling data before accepting a perf claim. Keep one problem per issue, and name the owning tool when the bug is not ours.

## Process

- **Titles and commits are short imperatives.** Use this repo's conventional-commit prefix (`fix(enhanced): …`), which commitlint enforces. Put regeneration in separate commits (`chore: update snapshots`).
- **Land a feature as one experimental PR, then small single-purpose fix PRs.** Write the PR body the way `AGENTS.md` asks, and say plainly what was not tested.
- **Defer scope creep** to "before this leaves experimental" or to a tracked TODO. Revert quickly when a change costs more than it gives.
Loading
Loading