-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: single runtime example (#4317)
* feat: single runtime example * upd * feat: single runtime example * feat: single runtime example * fix: add e2e tests * lint-staged * fix: add e2e tests * cix: update app and e2e * cix: update app and e2e * fix: update app and e2e * fix: update app and e2e
- Loading branch information
1 parent
d288f00
commit 834122a
Showing
21 changed files
with
2,497 additions
and
910 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,64 @@ | ||
# Controlled Vendor Sharing | ||
|
||
Dynamic Vendor Sharing is an application that implements a control panel in the runtime plugin for module federation 1.5 in rspack or `@module-federation/enhanced`. The control panel allows you to deterministically manage and modify the rules for shared modules, as well as upgrade or downgrade applications based on the inputs from the React form. | ||
This example demonstrates a runtime plugin implementation for Module Federation that provides dynamic control over shared module versions. It allows you to deterministically manage and modify shared module versions across federated applications using a control panel interface and localStorage persistence. | ||
|
||
## Features | ||
|
||
- Runtime plugin that implements rules for module sharing. | ||
- React form for modifying the rules. | ||
- Ability to upgrade or downgrade applications. | ||
- `app1` and `app2` exposing different button components. | ||
- Runtime plugin for dynamic version control of shared modules | ||
- Control panel UI for managing shared module versions | ||
- Persistent version settings using localStorage (`formDataVMSC` key) | ||
- Support for upgrading/downgrading shared module versions | ||
- E2E tests to verify version control functionality | ||
|
||
## Main Components | ||
|
||
### `./app1/control-share.ts` | ||
### `control-share.ts` | ||
|
||
This is the runtime plugin that implements the rules for module federation. | ||
A runtime plugin that implements version control for Module Federation. Key features: | ||
- Implements the `FederationRuntimePlugin` interface | ||
- Uses localStorage to persist version preferences | ||
- Handles version resolution and module sharing between applications | ||
- Manages share scope mapping and instance tracking | ||
|
||
### `./app1/src/ControlPanel.js` | ||
### E2E Tests (`checkAutomaticVendorApps.cy.ts`) | ||
|
||
This is a React form that allows for the modification of rules implemented in `control-share.ts`. | ||
Comprehensive E2E tests that verify: | ||
- Initial shared module versions | ||
- Version override functionality through localStorage | ||
- UI updates reflecting version changes | ||
- Button component rendering with correct version information | ||
|
||
# Running Demo | ||
## Running Demo | ||
|
||
Run `pnpm run start`. This will build and serve both `app1` and `app2` on ports 3001 and 3002 respectively. | ||
|
||
- [localhost:3001](http://localhost:3001/) | ||
- [localhost:3002](http://localhost:3002/) | ||
- [localhost:3001](http://localhost:3001/) - Host application with control panel | ||
- [localhost:3002](http://localhost:3002/) - Remote application | ||
|
||
# Running Cypress E2E Tests | ||
## Running Cypress E2E Tests | ||
|
||
To run tests in interactive mode, run `npm run cypress:debug` from the root directory of the project. It will open Cypress Test Runner and allow to run tests in interactive mode. [More info about "How to run tests"](../../cypress/README.md#how-to-run-tests) | ||
To run tests in interactive mode: | ||
```bash | ||
npm run cypress:debug | ||
``` | ||
|
||
To build app and run test in headless mode, run `yarn e2e:ci`. It will build app and run tests for this workspace in headless mode. If tets failed cypress will create `cypress` directory in sample root folder with screenshots and videos. | ||
To run tests in headless mode: | ||
```bash | ||
yarn e2e:ci | ||
``` | ||
|
||
["Best Practices, Rules amd more interesting information here](../../cypress/README.md) | ||
For failed tests, screenshots and videos will be saved in the `cypress` directory. | ||
|
||
## Implementation Details | ||
|
||
The control panel allows you to: | ||
- View current versions of shared modules (react, react-dom, lodash) | ||
- Override versions for specific applications | ||
- Save settings to localStorage | ||
- Clear settings and reload to default versions | ||
|
||
The runtime plugin (`control-share.ts`) handles: | ||
- Version resolution based on localStorage settings | ||
- Share scope management | ||
- Instance tracking and updates | ||
- Cross-application module sharing rules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,34 @@ | ||
import React from 'react'; | ||
|
||
const style = { | ||
background: '#800', | ||
background: '#ff4444', | ||
color: '#fff', | ||
padding: 12, | ||
padding: '12px 24px', | ||
border: 'none', | ||
borderRadius: '6px', | ||
fontSize: '16px', | ||
fontWeight: '600', | ||
cursor: 'pointer', | ||
transition: 'all 0.2s ease', | ||
boxShadow: '0 2px 4px rgba(0,0,0,0.2)', | ||
}; | ||
|
||
const Button = () => <button style={style}>App 1 Button</button>; | ||
const Button = () => ( | ||
<button | ||
style={style} | ||
onMouseEnter={(e) => { | ||
e.target.style.transform = 'translateY(-2px)'; | ||
e.target.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)'; | ||
e.target.style.background = '#ff5555'; | ||
}} | ||
onMouseLeave={(e) => { | ||
e.target.style.transform = 'translateY(0)'; | ||
e.target.style.boxShadow = '0 2px 4px rgba(0,0,0,0.2)'; | ||
e.target.style.background = '#ff4444'; | ||
}} | ||
> | ||
App 1 Button | ||
</button> | ||
); | ||
|
||
export default Button; |
Oops, something went wrong.