Skip to content

Commit 0fa20b0

Browse files
authored
Add shared context example (module-federation#14)
* add shared context example * update root readme
1 parent acc7d45 commit 0fa20b0

20 files changed

+232
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ This repository is to showcase examples on Webpack 5's new Module Federation can
1717
- [x] [Redux Reducer Injection](./redux-reducer-injection.md) — Dynamically inject reducers to host store at runtime.
1818
- [x] [Shared Routes](./shared-routes2) — Compose federated routes for a seamless user experience.
1919
- [ ] Nested Interleaved Components
20-
- [x] Share State/Context Providers
20+
- [x] [Share Context Provider](./shared-context/README.md) — App1 and App2 with shared Context Provider.
2121
- [ ] Non-UI Module
2222
- [x] Routing
2323
- [ ] Nested

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"comprehensive-demo/*",
1414
"server-side-rendering/*",
1515
"dynamic-system-host/*",
16+
"shared-context/*",
1617
"shared-routing/*",
1718
"shared-routes2/*",
1819
"typescript/*",

shared-context/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Shared Context Example
2+
3+
This example demos a host application wrapped in a ContextProvider and renders a remote component consuming the ContextProvider value.
4+
5+
- `app1` is the host application and is wrapped with `NameContextProvider` with value of `"Billy"`.
6+
- `app2` standalone application which exposes `Welcome` component. `Welcome` renders `"Welcome, <name>"`, where name is the value provided from `NameContextProvider.
7+
- `shared-library` is a library that would be shared between `app1` and `app2`. This library contains `NameContextProvider` component.
8+
9+
# Running Demo
10+
11+
Run `yarn start`. This will build and serve both `app1` and `app2` on ports 3001 and 3002 respectively.
12+
13+
- [localhost:3001](http://localhost:3001/)
14+
- [localhost:3002](http://localhost:3002/)

shared-context/app1/package.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "@shared-context/app1",
3+
"version": "0.0.0",
4+
"private": true,
5+
"devDependencies": {
6+
"@babel/core": "^7.9.0",
7+
"@babel/preset-react": "^7.9.1",
8+
"babel-loader": "^8.1.0",
9+
"html-webpack-plugin": "git://github.com/ScriptedAlchemy/html-webpack-plugin#master",
10+
"serve": "^11.3.0",
11+
"webpack": "git://github.com/webpack/webpack.git#dev-1",
12+
"webpack-cli": "^3.3.11",
13+
"webpack-dev-server": "^3.10.3"
14+
},
15+
"scripts": {
16+
"start": "webpack-dev-server",
17+
"build": "webpack --mode production",
18+
"serve": "serve dist -p 3001"
19+
},
20+
"dependencies": {
21+
"react": "^16.13.1",
22+
"react-dom": "^16.13.1"
23+
}
24+
}

shared-context/app1/public/index.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<html>
2+
<head>
3+
<script src="http://localhost:3002/remoteEntry.js"></script>
4+
</head>
5+
<body>
6+
<div id="root"></div>
7+
</body>
8+
</html>

shared-context/app1/src/App.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { NameContextProvider } from "@shared-context/shared-library";
2+
import React from "react";
3+
4+
const Welcome = React.lazy(() => import("app2/Welcome"));
5+
6+
const App = () => (
7+
<div>
8+
<h1>Context Provider</h1>
9+
<h2>App 1</h2>
10+
<NameContextProvider.Provider value="Billy">
11+
<React.Suspense fallback="Loading Name">
12+
<Welcome />
13+
</React.Suspense>
14+
</NameContextProvider.Provider>
15+
</div>
16+
);
17+
18+
export default App;

shared-context/app1/src/bootstrap.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import App from "./App";
2+
import React from "react";
3+
import ReactDOM from "react-dom";
4+
5+
ReactDOM.render(<App />, document.getElementById("root"));

shared-context/app1/src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import("./bootstrap");

shared-context/app1/webpack.config.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const HtmlWebpackPlugin = require("html-webpack-plugin");
2+
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
3+
const path = require("path");
4+
5+
module.exports = {
6+
entry: "./src/index",
7+
mode: "development",
8+
devServer: {
9+
contentBase: path.join(__dirname, "dist"),
10+
port: 3001,
11+
},
12+
output: {
13+
publicPath: "http://localhost:3001/",
14+
},
15+
module: {
16+
rules: [
17+
{
18+
test: /\.jsx?$/,
19+
loader: "babel-loader",
20+
options: {
21+
presets: ["@babel/preset-react"],
22+
},
23+
},
24+
],
25+
},
26+
plugins: [
27+
new ModuleFederationPlugin({
28+
name: "app1",
29+
library: { type: "var", name: "app1" },
30+
remotes: {
31+
app2: "app2",
32+
},
33+
shared: ["react", "react-dom", "@shared-context/shared-library"],
34+
}),
35+
new HtmlWebpackPlugin({
36+
template: "./public/index.html",
37+
}),
38+
],
39+
};

shared-context/app2/package.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "@shared-context/app2",
3+
"version": "0.0.0",
4+
"private": true,
5+
"devDependencies": {
6+
"@babel/core": "^7.9.0",
7+
"@babel/preset-react": "^7.9.1",
8+
"babel-loader": "^8.1.0",
9+
"html-webpack-plugin": "git://github.com/ScriptedAlchemy/html-webpack-plugin#master",
10+
"serve": "^11.3.0",
11+
"webpack": "git://github.com/webpack/webpack.git#dev-1",
12+
"webpack-cli": "^3.3.11",
13+
"webpack-dev-server": "^3.10.3"
14+
},
15+
"scripts": {
16+
"start": "webpack-dev-server",
17+
"build": "webpack --mode production",
18+
"serve": "serve dist -p 3002"
19+
},
20+
"dependencies": {
21+
"react": "^16.13.1",
22+
"react-dom": "^16.13.1"
23+
}
24+
}

shared-context/app2/public/index.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<html>
2+
<body>
3+
<div id="root"></div>
4+
</body>
5+
</html>

shared-context/app2/src/App.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { NameContextProvider } from "../../shared-library/src";
2+
import React from "react";
3+
import Welcome from "./Welcome";
4+
5+
const App = () => (
6+
<div>
7+
<h1>Context Provider</h1>
8+
<h2>App 2</h2>
9+
<NameContextProvider.Provider value="Susan">
10+
<Welcome />
11+
</NameContextProvider.Provider>
12+
</div>
13+
);
14+
15+
export default App;

shared-context/app2/src/Welcome.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { NameContextProvider } from "@shared-context/shared-library";
2+
import React from "react";
3+
4+
const Welcome = () => {
5+
const name = React.useContext(NameContextProvider);
6+
7+
return <p>Welcome, {name}</p>;
8+
};
9+
10+
export default Welcome;

shared-context/app2/src/bootstrap.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import App from "./App";
2+
import React from "react";
3+
import ReactDOM from "react-dom";
4+
5+
ReactDOM.render(<App />, document.getElementById("root"));

shared-context/app2/src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import("./bootstrap");

shared-context/app2/webpack.config.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const HtmlWebpackPlugin = require("html-webpack-plugin");
2+
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
3+
const path = require("path");
4+
5+
module.exports = {
6+
entry: "./src/index",
7+
mode: "development",
8+
devServer: {
9+
contentBase: path.join(__dirname, "dist"),
10+
port: 3002,
11+
},
12+
output: {
13+
publicPath: "http://localhost:3002/",
14+
},
15+
module: {
16+
rules: [
17+
{
18+
test: /\.jsx?$/,
19+
loader: "babel-loader",
20+
options: {
21+
presets: ["@babel/preset-react"],
22+
},
23+
},
24+
],
25+
},
26+
plugins: [
27+
new ModuleFederationPlugin({
28+
name: "app2",
29+
library: { type: "var", name: "app2" },
30+
filename: "remoteEntry.js",
31+
exposes: {
32+
Welcome: "./src/Welcome",
33+
},
34+
shared: ["react", "react-dom", "@shared-context/shared-library"],
35+
}),
36+
new HtmlWebpackPlugin({
37+
template: "./public/index.html",
38+
}),
39+
],
40+
};

shared-context/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"private": true,
3+
"scripts": {
4+
"start": "lerna run --scope @shared-context/* --parallel start",
5+
"build": "lerna run --scope @shared-context/* build",
6+
"serve": "lerna run --scope @shared-context/* --parallel serve"
7+
}
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "@shared-context/shared-library",
3+
"version": "0.0.0",
4+
"private": true,
5+
"main": "./src/index.js",
6+
"peerDependencies": {
7+
"react": "^16.13.0"
8+
}
9+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import React from "react";
2+
3+
export const NameContextProvider = React.createContext("No name provided");
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./NameContextProvider";

0 commit comments

Comments
 (0)