├── .gitignore ├── README.md ├── container ├── .babelrc ├── package-lock.json ├── package.json ├── src │ ├── App.jsx │ ├── index.css │ ├── index.html │ └── index.js └── webpack.config.js └── counter ├── .babelrc ├── package-lock.json ├── package.json ├── src ├── App.jsx ├── components │ └── Counter.jsx ├── index.css ├── index.html └── index.js └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # micro -------------------------------------------------------------------------------- /container/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-react", "@babel/preset-env"], 3 | "plugins": [ 4 | ["@babel/transform-runtime"] 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /container/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "container", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "build": "webpack --mode production", 6 | "build:dev": "webpack --mode development", 7 | "build:start": "cd dist && PORT=8080 npx serve", 8 | "start": "webpack serve --open --mode development", 9 | "start:live": "webpack serve --open --mode development --live-reload --hot" 10 | }, 11 | "license": "MIT", 12 | "author": { 13 | "name": "Jack Herrington", 14 | "email": "jherr@pobox.com" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.15.8", 18 | "@babel/plugin-transform-runtime": "^7.15.8", 19 | "@babel/preset-env": "^7.15.8", 20 | "@babel/preset-react": "^7.14.5", 21 | "autoprefixer": "^10.1.0", 22 | "babel-loader": "^8.2.2", 23 | "css-loader": "^6.3.0", 24 | "html-webpack-plugin": "^5.3.2", 25 | "postcss": "^8.2.1", 26 | "postcss-loader": "^4.1.0", 27 | "style-loader": "^3.3.0", 28 | "webpack": "^5.57.1", 29 | "webpack-cli": "^4.9.0", 30 | "webpack-dev-server": "^4.3.1" 31 | }, 32 | "dependencies": { 33 | "@babel/runtime": "^7.13.10", 34 | "react": "^17.0.2", 35 | "react-dom": "^17.0.2" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /container/src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { Counter } from 'counter/Counter'; 4 | 5 | import "./index.css"; 6 | 7 | const App = () => ( 8 |
9 |

Container App

10 | 11 |
12 | ); 13 | ReactDOM.render(, document.getElementById("app")); 14 | -------------------------------------------------------------------------------- /container/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, Helvetica, sans-serif; 3 | } 4 | 5 | .container { 6 | margin: auto; 7 | max-width: 800px; 8 | margin-top: 20px; 9 | } 10 | -------------------------------------------------------------------------------- /container/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | container 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /container/src/index.js: -------------------------------------------------------------------------------- 1 | import("./App"); 2 | -------------------------------------------------------------------------------- /container/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebPackPlugin = require("html-webpack-plugin"); 2 | const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); 3 | 4 | const deps = require("./package.json").dependencies; 5 | module.exports = { 6 | output: { 7 | publicPath: "http://localhost:8080/", 8 | }, 9 | resolve: { 10 | extensions: [".tsx", ".ts", ".jsx", ".js", ".json"], 11 | }, 12 | devServer: { 13 | port: 8080, 14 | historyApiFallback: true, 15 | }, 16 | module: { 17 | rules: [ 18 | { 19 | test: /\.m?js/, 20 | type: "javascript/auto", 21 | resolve: { 22 | fullySpecified: false, 23 | }, 24 | }, 25 | { 26 | test: /\.(css|s[ac]ss)$/i, 27 | use: ["style-loader", "css-loader", "postcss-loader"], 28 | }, 29 | { 30 | test: /\.(ts|tsx|js|jsx)$/, 31 | exclude: /node_modules/, 32 | use: { 33 | loader: "babel-loader", 34 | }, 35 | }, 36 | ], 37 | }, 38 | plugins: [ 39 | new ModuleFederationPlugin({ 40 | name: "container", 41 | filename: "remoteEntry.js", 42 | remotes: { 43 | counter: "counter@http://localhost:8081/remoteEntry.js", 44 | }, 45 | exposes: {}, 46 | shared: { 47 | ...deps, 48 | react: { 49 | singleton: true, 50 | requiredVersion: deps.react, 51 | }, 52 | "react-dom": { 53 | singleton: true, 54 | requiredVersion: deps["react-dom"], 55 | }, 56 | }, 57 | }), 58 | new HtmlWebPackPlugin({ 59 | template: "./src/index.html", 60 | }), 61 | ], 62 | }; 63 | -------------------------------------------------------------------------------- /counter/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-react", "@babel/preset-env"], 3 | "plugins": [ 4 | ["@babel/transform-runtime"] 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /counter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "counter", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "build": "webpack --mode production", 6 | "build:dev": "webpack --mode development", 7 | "build:start": "cd dist && PORT=8081 npx serve", 8 | "start": "webpack serve --open --mode development", 9 | "start:live": "webpack serve --open --mode development --live-reload --hot" 10 | }, 11 | "license": "MIT", 12 | "author": { 13 | "name": "Jack Herrington", 14 | "email": "jherr@pobox.com" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.15.8", 18 | "@babel/plugin-transform-runtime": "^7.15.8", 19 | "@babel/preset-env": "^7.15.8", 20 | "@babel/preset-react": "^7.14.5", 21 | "autoprefixer": "^10.1.0", 22 | "babel-loader": "^8.2.2", 23 | "css-loader": "^6.3.0", 24 | "html-webpack-plugin": "^5.3.2", 25 | "postcss": "^8.2.1", 26 | "postcss-loader": "^4.1.0", 27 | "style-loader": "^3.3.0", 28 | "webpack": "^5.57.1", 29 | "webpack-cli": "^4.9.0", 30 | "webpack-dev-server": "^4.3.1" 31 | }, 32 | "dependencies": { 33 | "@babel/runtime": "^7.13.10", 34 | "react": "^17.0.2", 35 | "react-dom": "^17.0.2" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /counter/src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { Counter } from "./components/Counter"; 4 | 5 | import "./index.css"; 6 | 7 | const App = () => ( 8 |
9 | 10 |
11 | ); 12 | ReactDOM.render(, document.getElementById("app")); 13 | -------------------------------------------------------------------------------- /counter/src/components/Counter.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | 3 | export const Counter = () => { 4 | const [count, setCount] = useState(0); 5 | const onIncrement = () => setCount(count + 1); 6 | const onDecrement = () => setCount(count - 1); 7 | 8 | return ( 9 |
10 |

Counter App

11 |

Current count: {count}

12 | 13 | 14 |
15 | ); 16 | } -------------------------------------------------------------------------------- /counter/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, Helvetica, sans-serif; 3 | } 4 | 5 | .container { 6 | margin: auto; 7 | max-width: 800px; 8 | margin-top: 20px; 9 | } 10 | -------------------------------------------------------------------------------- /counter/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | counter 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /counter/src/index.js: -------------------------------------------------------------------------------- 1 | import("./App"); 2 | -------------------------------------------------------------------------------- /counter/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebPackPlugin = require("html-webpack-plugin"); 2 | const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); 3 | 4 | const deps = require("./package.json").dependencies; 5 | module.exports = { 6 | output: { 7 | publicPath: "http://localhost:8081/", 8 | }, 9 | 10 | resolve: { 11 | extensions: [".tsx", ".ts", ".jsx", ".js", ".json"], 12 | }, 13 | 14 | devServer: { 15 | port: 8081, 16 | historyApiFallback: true, 17 | }, 18 | 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.m?js/, 23 | type: "javascript/auto", 24 | resolve: { 25 | fullySpecified: false, 26 | }, 27 | }, 28 | { 29 | test: /\.(css|s[ac]ss)$/i, 30 | use: ["style-loader", "css-loader", "postcss-loader"], 31 | }, 32 | { 33 | test: /\.(ts|tsx|js|jsx)$/, 34 | exclude: /node_modules/, 35 | use: { 36 | loader: "babel-loader", 37 | }, 38 | }, 39 | ], 40 | }, 41 | 42 | plugins: [ 43 | new ModuleFederationPlugin({ 44 | name: "counter", 45 | filename: "remoteEntry.js", 46 | remotes: {}, 47 | exposes: { 48 | "./Counter": "./src/components/Counter", 49 | }, 50 | shared: { 51 | ...deps, 52 | react: { 53 | singleton: true, 54 | requiredVersion: deps.react, 55 | }, 56 | "react-dom": { 57 | singleton: true, 58 | requiredVersion: deps["react-dom"], 59 | }, 60 | }, 61 | }), 62 | new HtmlWebPackPlugin({ 63 | template: "./src/index.html", 64 | }), 65 | ], 66 | }; 67 | --------------------------------------------------------------------------------