Skip to content

Comments

STRIPES-861 integration of module federation logic in the main branch.#173

Merged
JohnC-80 merged 68 commits intomainfrom
STRIPES-861-int
Feb 3, 2026
Merged

STRIPES-861 integration of module federation logic in the main branch.#173
JohnC-80 merged 68 commits intomainfrom
STRIPES-861-int

Conversation

@JohnC-80
Copy link
Contributor

@JohnC-80 JohnC-80 commented Dec 5, 2025

This PR takes the logic from #105 and places it behind a conditional on an okapi.discoveryUrl field in the stripes-config object.

Further adjustment - StripesTranslationPlugin accumulates translations from included stripesDeps (stripes-acq-components, etc) so that those can be loaded at runtime when the dependent ui-module's translations are loaded.

StripesTranslationPlugin contains a conditional where it doesn't piggyback onto stripesConfigPlugin for federated module builds.

LocalFederationPlugin is used for spinning up a local set of remotes of the modules via local stripes-config. It loops through the modules and spawns a federate process. If modules is empty, this does nothing.

Conforms module federation behavior to serve --federate and build --federate commands.
Will pull shared dependencies from the locally installed copy of stripes-core, if possible, falling back to reach out to stripes-core on github if the local stripes-core can't be required.

Module Usage

Clone, yarn your module, and in your console of choice (within the module directory):

yarn stripes build --federate

It will generate an output directory with your built module's files.

Module build troubleshooting

Typescript

'@types/react' resolution... react's types have a greedy dependency version (*). If it isn't controlled via resolutions, it will install types for v19 even if v18 is used by your project. The solution is to set the resolution in your project's package.json to ensure that the correct version is installed: Platform-complete does this and now that builds are possible at the module level, so should you!
in package.json:

"resolutions": {
    "@types/react": "^18"
  }

Every module

Ensure that your main key in package.json points to an existing file. Conventionally, this is src/index.js or (TS) src/index.tsx.
The module-level build sets this file as its webpack entry point. If this doesn't exist, the build will fail.

React context:

As of this writing, libraries like stripes-acq-components, stripes-inventory-components, etc do not have to be independently built for module-federation. They are dependencies and can be used as normal. If a particular package isn't provided as a singleton by the host app, then a module will used its own version. This can/will cause duplicates of the same library to be loaded, and this will cause a problem with React context. If one module has a provider, and loads a plugin module within, which uses the same context, the separate dependencies could end up looking at different instances of the context, which will not work and could result in ui-crashes and empty context values. The solution we're investigating is to make use of react-singleton-context in the libraries that we can control. For more info: npm module react-singleton-context

Other context-heavy dependencies that cross the boundaries between UI modules should be marked as singletons with the host app.

@github-actions
Copy link

github-actions bot commented Dec 5, 2025

Jest Unit Test Results

0 tests  ±0   0 ✅ ±0   0s ⏱️ ±0s
0 suites ±0   0 💤 ±0 
0 files   ±0   0 ❌ ±0 

Results for commit ac25039. ± Comparison against base commit d7cb74e.

♻️ This comment has been updated with latest results.

@JohnC-80 JohnC-80 changed the title Stripes-861 integration of module federation logic in the main branch. STRIPES-861 integration of module federation logic in the main branch. Dec 5, 2025
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 3, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots
0.0% Coverage on New Code (required ≥ 80%)
6.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

JohnC-80 added a commit to folio-org/stripes-core that referenced this pull request Feb 3, 2026
#1679)

This PR takes the logic from #105 and implements backward
compatibility/opt-in behavior to module federation. Huge thanks to
@mkuklis so long ago for his initial lift!

This works with the [Stripes-webpack
PR](folio-org/stripes-webpack#173) and
[STRIPES-CLI PR](folio-org/stripes-cli#392) to
run a federated ui platform.

The changes in this PR implement an `<EntitlementLoader>` component
that, provided an `entitlementUrl` via `stripes-config.okapi`, will
fetch its list of modules from a dynamic source containing URL's for
those module bundles. The bundles are then prefetched individually,
translations, icons, loaded. The component passes through any modules
provided via the monolithic build `stripes-config` setup.

Adds `addIcon` and adjusts `setTranslations` reducers to accumulate
translations from async remote modules (loaded all together up front
rather than on-demand at instanciation points such as AppRoutes and
Settings (so the synchronous syntax of those implementations remain the
same.)

Try the script to clone applicable branches, a few modules and set up a
workspace:

````bash
mkdir -p module_federation && cd module_federation

# checkout all stripes modules
stripes_modules=(
  webpack
  core
  cli
)

for m in "${stripes_modules[@]}"; do
  git clone "https://github.com/folio-org/stripes-$m.git" --branch STRIPES-861-int &
done

git clone "https://github.com/folio-org/stripes-ui.git"

git clone "https://github.com/folio-org/ui-users.git" &
git clone "https://github.com/folio-org/ui-inventory.git" &
wait

# create workspace via package.json
cat > package.json <<EOF
{
  "private": true,
  "workspaces": [
    "*"
  ]
}
EOF

# create stripes.config
cat > stripes.config.js <<EOF
module.exports = {
  okapi: {
    url: 'https://folio-snapshot-okapi.dev.folio.org',
    tenant: 'diku',
    entitlementUrl: 'http://localhost:3001/registry'
  },
  config: {
    logCategories: 'core,path,action,xhr',
    logPrefix: '--',
    showPerms: false,
    hasAllPerms: false,
    languages: ['en'],
    suppressIntlErrors: true,
  },
  modules: {
  }
};
EOF

# install dependencies
yarn
````

Then you can: 
Build a module-federation host app (from the workspace level):
```
yarn stripes build --federate stripes.config.js
```
Serve the host app (dev mode from the workspace level)
```
yarn stripes serve --federate stripes.config.js
```

Build module bundle for static hosting (at the ui-module level)
```
yarn stripes build --federate
```
Serving the federated ui-module (dev mode at the ui-module level)
```
yarn stripes serve --federate
```

Have fun! 🎉🚀🎸🤘

---------

Co-authored-by: Michal Kuklis <michal.kuklis@gmail.com>
Co-authored-by: Zak Burke <zburke@ebsco.com>
@JohnC-80 JohnC-80 merged commit 2ddd418 into main Feb 3, 2026
14 of 15 checks passed
@JohnC-80 JohnC-80 deleted the STRIPES-861-int branch February 3, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants