Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
8686d8e
feat(repack): add federation manifest schema, builder and emitter
gedu Sep 21, 2026
a5b01b6
feat(repack): wire opt-in manifest option into module federation plugins
gedu Sep 21, 2026
75c9a1a
docs(repack): document the opt-in federation manifest
gedu Sep 21, 2026
6205e34
feat(repack): add federation manifest inspection and doctor commands
gedu Sep 21, 2026
544fc8e
fix(repack): exclude synthetic deep-import keys from the federation m…
gedu Sep 21, 2026
12ddc48
style(repack): format federation manifest shared assertion
gedu Sep 21, 2026
c5df67f
fix(repack): report conventional host-eager/remote-lazy as EAGER_ADVI…
gedu Sep 21, 2026
6c06f0b
refactor(repack): share installed-version resolver via lazy builtin a…
gedu Sep 21, 2026
3e01004
feat(repack): add defineShared exact-pin shared-config helper
gedu Sep 21, 2026
7d06ba8
feat(repack): add repack-federation.json loader with zero-flag doctor…
gedu Sep 21, 2026
caefb4f
feat(repack): doctor pairwise opt-in, role-aware eager advisory, host…
gedu Sep 21, 2026
bf78dee
feat(repack): add plugin shared extraction and doctor --dry-run pre-b…
gedu Sep 21, 2026
eaf49ea
feat(repack): add runtime-only --standalone mode via env.argv with to…
gedu Sep 21, 2026
622501d
feat(repack): add feature-folder static scanner with dynamic-import a…
gedu Sep 21, 2026
c664531
feat(repack): add federation-init plan engine (idempotent, diff-befor…
gedu Sep 22, 2026
04acc00
feat(repack): register flat federation-init command and docs
gedu Sep 22, 2026
b9a2b08
refactor(testers): migrate federation tester configs to defineShared
gedu Sep 22, 2026
49716da
fix(repack): pass CLI positional args and discover init-generated con…
gedu Sep 22, 2026
6b6758f
docs(repack): federation workspace workflow guide and design-doc corr…
gedu Sep 22, 2026
d660cda
feat(repack): add config and host port fields to federation config sc…
gedu Sep 22, 2026
9743ffa
refactor(repack): make federation standalone gate name-keyed
gedu Sep 22, 2026
fe5360d
fix(repack): use declared config for dry-run shared attribution
gedu Sep 22, 2026
702adb3
feat(repack): resolve local react-native cli for federation runner
gedu Sep 22, 2026
47bd150
feat(repack): add federation dev plan resolver
gedu Sep 22, 2026
a86d00a
feat(repack): add federation dev port planner
gedu Sep 22, 2026
de04b1b
feat(repack): add execa dev supervisor for federation sessions
gedu Sep 22, 2026
32875ae
feat(repack): add runner console sink
gedu Sep 22, 2026
4dd4059
feat(repack): add federation dev plan/status tables
gedu Sep 22, 2026
9b01c07
feat(repack): add federation-dev command with dry-run and json output
gedu Sep 22, 2026
f55d697
feat(repack): wire federation-dev live session with exit codes
gedu Sep 22, 2026
edabef5
fix(dev-server): build url from normalized port
gedu Sep 22, 2026
aaca321
feat(repack): add federation-dev interactive wizard
gedu Sep 22, 2026
9720cb8
feat(repack): add live status block and keymap to federation-dev
gedu Sep 22, 2026
c0322fc
chore(tester-federation): adopt config fields and federation-dev scripts
gedu Sep 22, 2026
d5dfec4
docs(website): document federation-dev command
gedu Sep 22, 2026
9cd5304
docs: record federation-dev as-built design deviations
gedu Sep 22, 2026
0e50e3d
feat(repack): show repack banner in federation dev
gedu Sep 22, 2026
644ca70
fix(repack): show key legends in federation-dev wizard
gedu Sep 22, 2026
a11f6f9
Revert "fix(repack): show key legends in federation-dev wizard"
gedu Sep 22, 2026
6b66079
docs: record wizard chrome constraints and TUI guidance
gedu Sep 22, 2026
63cc795
test(repack): spell control bytes as escapes in portPlanner test
gedu Sep 22, 2026
b7bab56
fix(repack): follow effective plan platform in federation-dev guidance
gedu Sep 22, 2026
6cb1dd3
fix(repack): resolve each app react-native CLI from its own root
gedu Sep 22, 2026
a86a579
feat(repack): add --config flag to federation-dev
gedu Sep 22, 2026
86c0568
chore(tester-federation-v2): adopt federation-dev workspace map and s…
gedu Sep 22, 2026
204c185
refactor(repack): drop unfired app-exit shutdown reason from supervisor
gedu Sep 22, 2026
859138c
test(repack): pin dry-run port-conflict wiring at command level
gedu Sep 22, 2026
a0b339e
docs(website): cover config flag, per-app CLI, v2 usage and dead-host…
gedu Sep 22, 2026
a43f756
test(repack): generate rnBin fixtures at runtime for CI
gedu Sep 22, 2026
c928a2f
feat(repack): plan the app-launch command for federation-dev
gedu Sep 22, 2026
c172d4c
feat(repack): attach one-shot processes to the dev supervisor
gedu Sep 22, 2026
2b12118
feat(repack): ask the wizard whether to launch the app when ready
gedu Sep 22, 2026
268b442
feat(repack): launch the app on the device once federation-dev is ready
gedu Sep 22, 2026
f1e39af
docs(website): document app auto-launch for federation-dev
gedu Sep 22, 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
7 changes: 7 additions & 0 deletions .changeset/federation-manifest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@callstack/repack': minor
---

Add an opt-in `manifest` option to both module federation plugins. When set, the build emits `repack-federation-manifest.json` next to the bundle: shared dependencies report the versions actually installed in `node_modules` instead of the `*` range the plugins configure by default, and an additive `reactNative` block lists the native modules found in the module graph. Field shapes follow the upstream `mf-manifest.json` spec, so existing tooling can parse the file as-is. With the option absent, builds are byte-identical to before.

Two commands consume the manifest. `npx react-native federation-manifest <file|dir|url>` prints a human-readable summary of what a host or remote shipped, or the raw document with `--json`. `npx react-native federation-doctor --host <source> --remotes <list>` compares a host manifest against its remotes and reports singleton version drift, `singleton`/`eager` mismatches, unresolvable `requiredVersion` ranges, native modules the host does not declare, and remotes that ship no manifest. It exits 1 on drift and 2 when a check could not run, so it works as a CI gate; `--format json` and `--allow-missing-manifests` cover scripts and gradual rollout.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,13 @@ packages/**/docs

# watchman
.watchman-cookie*

# Fixture node_modules for federation manifest / defineShared version tests
!packages/repack/src/plugins/__tests__/__fixtures__/manifest-context/node_modules/
!packages/repack/src/utils/__tests__/__fixtures__/define-shared-app/node_modules/
!packages/repack/src/utils/__tests__/__fixtures__/define-shared-split-app/node_modules/
!packages/repack/src/commands/federation/__fixtures__/dry-run-workspace/apps/host/node_modules/
!packages/repack/src/commands/federation/__fixtures__/dry-run-workspace/apps/remote-clean/node_modules/
!packages/repack/src/commands/federation/__fixtures__/dry-run-workspace/apps/remote-drift/node_modules/
!packages/repack/src/commands/federation/__fixtures__/init-workspace/apps/host/node_modules/
!packages/repack/src/commands/federation/__fixtures__/init-workspace/apps/remote-drift/node_modules/
1 change: 1 addition & 0 deletions agent_context/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ works, and is kept in sync with the implementation as it evolves.
| Folder | Topic |
| --- | --- |
| [rspackv2-jul2026](./rspackv2-jul2026/design.md) | Dual Rspack 1.x/2.x support |
| [federation-tools](./federation-tools/design.md) | Federation manifest, doctor, shared-config retrofit, dev runner |
401 changes: 401 additions & 0 deletions agent_context/federation-tools/design.md

Large diffs are not rendered by default.

57 changes: 16 additions & 41 deletions apps/tester-federation-v2/configs/rspack.host-app.mts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import * as Repack from '@callstack/repack';
import rspack from '@rspack/core';
import reactPkg from 'react/package.json' with { type: 'json' };
import reactNativePkg from 'react-native/package.json' with { type: 'json' };
import pkg from '../package.json' with { type: 'json' };

// Shared dependencies are versionless here: defineShared pins every entry to
// the exact version installed in this workspace, so host and remotes always
// agree without hand-maintained literals.
const SHARED_DEPS = [
'react',
'react-native',
'@react-navigation/native',
'@react-navigation/native-stack',
'react-native-safe-area-context',
'react-native-screens',
];

export default Repack.defineRspackConfig((env) => {
const { mode, context, platform } = env;
Expand Down Expand Up @@ -52,44 +61,10 @@ export default Repack.defineRspackConfig((env) => {
MiniApp: `MiniApp@http://localhost:8082/${platform}/mf-manifest.json`,
},
dts: false,
shared: {
react: {
singleton: true,
eager: true,
version: reactPkg.version,
requiredVersion: reactPkg.version,
},
'react-native': {
singleton: true,
eager: true,
version: reactNativePkg.version,
requiredVersion: reactNativePkg.version,
},
'@react-navigation/native': {
singleton: true,
eager: true,
version: pkg.dependencies['@react-navigation/native'],
requiredVersion: pkg.dependencies['@react-navigation/native'],
},
'@react-navigation/native-stack': {
singleton: true,
eager: true,
version: pkg.dependencies['@react-navigation/native-stack'],
requiredVersion: pkg.dependencies['@react-navigation/native-stack'],
},
'react-native-safe-area-context': {
singleton: true,
eager: true,
version: pkg.dependencies['react-native-safe-area-context'],
requiredVersion: pkg.dependencies['react-native-safe-area-context'],
},
'react-native-screens': {
singleton: true,
eager: true,
version: pkg.dependencies['react-native-screens'],
requiredVersion: pkg.dependencies['react-native-screens'],
},
},
shared: Repack.defineShared(SHARED_DEPS, {
context,
role: 'host',
}),
}),
// silence missing @react-native-masked-view optionally required by @react-navigation/elements
new rspack.IgnorePlugin({
Expand Down
59 changes: 18 additions & 41 deletions apps/tester-federation-v2/configs/rspack.mini-app.mts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import * as Repack from '@callstack/repack';
import rspack from '@rspack/core';
import reactPkg from 'react/package.json' with { type: 'json' };
import reactNativePkg from 'react-native/package.json' with { type: 'json' };
import pkg from '../package.json' with { type: 'json' };

// Shared dependencies are versionless here: defineShared pins every entry to
// the exact version installed in this workspace, so host and remotes always
// agree without hand-maintained literals.
const SHARED_DEPS = [
'react',
'react-native',
'@react-navigation/native',
'@react-navigation/native-stack',
'react-native-safe-area-context',
'react-native-screens',
];

export default Repack.defineRspackConfig((env) => {
const { mode, context, platform } = env;
Expand Down Expand Up @@ -49,44 +58,12 @@ export default Repack.defineRspackConfig((env) => {
'./MiniAppNavigator': './src/mini/navigation/MainNavigator',
},
dts: false,
shared: {
react: {
singleton: true,
eager: false,
version: reactPkg.version,
requiredVersion: reactPkg.version,
},
'react-native': {
singleton: true,
eager: false,
version: reactNativePkg.version,
requiredVersion: reactNativePkg.version,
},
'@react-navigation/native': {
singleton: true,
eager: false,
version: pkg.dependencies['@react-navigation/native'],
requiredVersion: pkg.dependencies['@react-navigation/native'],
},
'@react-navigation/native-stack': {
singleton: true,
eager: false,
version: pkg.dependencies['@react-navigation/native-stack'],
requiredVersion: pkg.dependencies['@react-navigation/native-stack'],
},
'react-native-safe-area-context': {
singleton: true,
eager: false,
version: pkg.dependencies['react-native-safe-area-context'],
requiredVersion: pkg.dependencies['react-native-safe-area-context'],
},
'react-native-screens': {
singleton: true,
eager: false,
version: pkg.dependencies['react-native-screens'],
requiredVersion: pkg.dependencies['react-native-screens'],
},
},
shared: Repack.defineShared(SHARED_DEPS, {
context,
role: 'remote',
// `--standalone` is runtime-only (env.argv): never committed.
mode: env.argv?.standalone ? 'standalone' : 'federated',
}),
}),
// silence missing @react-native-masked-view optionally required by @react-navigation/elements
new rspack.IgnorePlugin({
Expand Down
57 changes: 16 additions & 41 deletions apps/tester-federation-v2/configs/webpack.host-app.mts
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
// @ts-check
import * as Repack from '@callstack/repack';
import reactPkg from 'react/package.json' with { type: 'json' };
import reactNativePkg from 'react-native/package.json' with { type: 'json' };
import webpack from 'webpack';
import pkg from '../package.json' with { type: 'json' };

// Shared dependencies are versionless here: defineShared pins every entry to
// the exact version installed in this workspace, so host and remotes always
// agree without hand-maintained literals.
const SHARED_DEPS = [
'react',
'react-native',
'@react-navigation/native',
'@react-navigation/native-stack',
'react-native-safe-area-context',
'react-native-screens',
];

export default Repack.defineWebpackConfig((env) => {
const { mode, context, platform } = env;
Expand Down Expand Up @@ -48,44 +57,10 @@ export default Repack.defineWebpackConfig((env) => {
MiniApp: `MiniApp@http://localhost:8082/${platform}/mf-manifest.json`,
},
dts: false,
shared: {
react: {
singleton: true,
eager: true,
version: reactPkg.version,
requiredVersion: reactPkg.version,
},
'react-native': {
singleton: true,
eager: true,
version: reactNativePkg.version,
requiredVersion: reactNativePkg.version,
},
'@react-navigation/native': {
singleton: true,
eager: true,
version: pkg.dependencies['@react-navigation/native'],
requiredVersion: pkg.dependencies['@react-navigation/native'],
},
'@react-navigation/native-stack': {
singleton: true,
eager: true,
version: pkg.dependencies['@react-navigation/native-stack'],
requiredVersion: pkg.dependencies['@react-navigation/native-stack'],
},
'react-native-safe-area-context': {
singleton: true,
eager: true,
version: pkg.dependencies['react-native-safe-area-context'],
requiredVersion: pkg.dependencies['react-native-safe-area-context'],
},
'react-native-screens': {
singleton: true,
eager: true,
version: pkg.dependencies['react-native-screens'],
requiredVersion: pkg.dependencies['react-native-screens'],
},
},
shared: Repack.defineShared(SHARED_DEPS, {
context,
role: 'host',
}),
}),
// silence missing @react-native-masked-view optionally required by @react-navigation/elements
new webpack.IgnorePlugin({
Expand Down
59 changes: 18 additions & 41 deletions apps/tester-federation-v2/configs/webpack.mini-app.mts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import * as Repack from '@callstack/repack';
import reactPkg from 'react/package.json' with { type: 'json' };
import reactNativePkg from 'react-native/package.json' with { type: 'json' };
import webpack from 'webpack';
import pkg from '../package.json' with { type: 'json' };

// Shared dependencies are versionless here: defineShared pins every entry to
// the exact version installed in this workspace, so host and remotes always
// agree without hand-maintained literals.
const SHARED_DEPS = [
'react',
'react-native',
'@react-navigation/native',
'@react-navigation/native-stack',
'react-native-safe-area-context',
'react-native-screens',
];

export default Repack.defineWebpackConfig((env) => {
const { mode, context, platform } = env;
Expand Down Expand Up @@ -47,44 +56,12 @@ export default Repack.defineWebpackConfig((env) => {
'./MiniAppNavigator': './src/mini/navigation/MainNavigator',
},
dts: false,
shared: {
react: {
singleton: true,
eager: false,
version: reactPkg.version,
requiredVersion: reactPkg.version,
},
'react-native': {
singleton: true,
eager: false,
version: reactNativePkg.version,
requiredVersion: reactNativePkg.version,
},
'@react-navigation/native': {
singleton: true,
eager: false,
version: pkg.dependencies['@react-navigation/native'],
requiredVersion: pkg.dependencies['@react-navigation/native'],
},
'@react-navigation/native-stack': {
singleton: true,
eager: false,
version: pkg.dependencies['@react-navigation/native-stack'],
requiredVersion: pkg.dependencies['@react-navigation/native-stack'],
},
'react-native-safe-area-context': {
singleton: true,
eager: false,
version: pkg.dependencies['react-native-safe-area-context'],
requiredVersion: pkg.dependencies['react-native-safe-area-context'],
},
'react-native-screens': {
singleton: true,
eager: false,
version: pkg.dependencies['react-native-screens'],
requiredVersion: pkg.dependencies['react-native-screens'],
},
},
shared: Repack.defineShared(SHARED_DEPS, {
context,
role: 'remote',
// `--standalone` is runtime-only (env.argv): never committed.
mode: env.argv?.standalone ? 'standalone' : 'federated',
}),
}),
// silence missing @react-native-masked-view optionally required by @react-navigation/elements
new webpack.IgnorePlugin({
Expand Down
4 changes: 2 additions & 2 deletions apps/tester-federation-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"ios": "react-native run-ios --no-packager",
"pods": "(cd ios && bundle install && (bundle exec pod install || bundle exec pod update))",
"pods:update": "(cd ios && bundle install && bundle exec pod update)",
"start:hostapp": "react-native webpack-start --config config.host-app.mts",
"start:miniapp": "react-native webpack-start --config config.mini-app.mts --port 8082"
"start": "react-native federation-dev",
"start:dry": "react-native federation-dev --dry-run"
},
"dependencies": {
"@callstack/repack": "workspace:*",
Expand Down
17 changes: 17 additions & 0 deletions apps/tester-federation-v2/repack-federation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"host": {
"root": ".",
"manifest": "build/host-app/ios",
"config": "config.host-app.mts",
"port": 8081
},
"remotes": {
"MiniApp": {
"root": ".",
"manifest": "build/mini-app/ios",
"standalone": true,
"port": 8082,
"config": "config.mini-app.mts"
}
}
}
Loading
Loading