Open wuxianqiang opened 3 years ago
WHAT(Module Federation 是什么?)
Module Federation [ˌfedəˈreɪʃn] 使 JavaScript 应用得以在客户端或服务器上动态运行另一个 bundle 的代码。
这其中的关键点是:动态,包含两个含义:
1、按需,可以把一个包拆开来加载其中一部分;
2、运行时,跑在浏览器而非 node 编译时;
另一个 bundle 的代码,之前应用之间做共享是在文件级或 npm 包级 export 成员,现在可以在应用级 export 成员属性。
Module Federation 里有两个主要概念 host 和 remote。每个项目可以是 host 也可以是 remote,也可以两个都是。
webpack.config.js
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); module.exports = { mode: "development", entry: "./src/index.js", cache: { type: "filesystem", cacheDirectory: path.resolve(__dirname, "node_modules/.cache/webpack"), }, output: { filename: "bundle.js", path: path.resolve(__dirname, "dist"), publicPath: "http://localhost:8000/", }, devServer: { port: 8000, }, optimization: { usedExports: true, }, devtool: false, module: { rules: [ { test: /\.js$/, use: [ { loader: "babel-loader", options: { presets: ["@babel/preset-react"], }, }, ], exclude: /node_modules/, }, { test: /\.png$/, type: "asset/resource", }, { test: /\.css$/, use: ["style-loader", "css-loader"], }, ], }, plugins: [ new HtmlWebpackPlugin({ template: "./public/index.html", }), new ModuleFederationPlugin({ // 这里是重点部分 filename: "remoteEntry.js", name: "remote", exposes: { "./NewsList": "./src/NewsList", }, }), ], };
src/index.js
import("./bootstrap");
src/bootstrap.js
import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; ReactDOM.render(<App />, document.getElementById("root"));
src/App.js
import React from "react"; import NewsList from './NewsList'; const App = () => ( <div> <h2>本地组件NewsList</h2> <NewsList /> </div> ); export default App;
src/NewsList.js 这个组件导出给别人使用,在 webpack 配置中可以看到。
import React from "react"; export default ()=>( <div>新闻列表</div> )
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); module.exports = { mode: "development", entry: "./src/index.js", cache: { type: "filesystem", cacheDirectory: path.resolve(__dirname, "node_modules/.cache/webpack"), }, output: { filename: "bundle.js", path: path.resolve(__dirname, "dist"), publicPath: "http://localhost:9000/", }, devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, port: 9000, }, optimization: { usedExports: true, }, devtool: false, module: { rules: [ { test: /\.js$/, use: [ { loader: "babel-loader", options: { presets: ["@babel/preset-react"], }, }, ], exclude: /node_modules/, }, { test: /\.png$/, type: "asset/resource", }, { test: /\.css$/, use: ["style-loader", "css-loader"], }, ], }, plugins: [ new HtmlWebpackPlugin({ template: "./public/index.html", }), new ModuleFederationPlugin({ // 这里是重点部分 filename: "remoteEntry.js", name: "host", remotes: { remote: "remote@http://localhost:8000/remoteEntry.js" } }) ], };
src/App.js 中导入了之前别人写好的 NewsList 组件,在 webpack 配置中可以看到。
import React from "react"; const RemoteNewsList = React.lazy(() => import("remote/NewsList")); const App = () => ( <div> <h2 >远程组件NewsList</h2> <React.Suspense fallback="Loading NewsList"> <RemoteNewsList /> </React.Suspense> </div> ); export default App;
A 应用可以引用 B 整个应用,也可以应用 B 的页面和组件。这样一来,灵活性就非常大了。
${name}/${expose}
以上代码都可以在我的demo中看到:https://github.com/wuxianqiang/webacpk5-remote
WHAT(Module Federation 是什么?)
Module Federation [ˌfedəˈreɪʃn] 使 JavaScript 应用得以在客户端或服务器上动态运行另一个 bundle 的代码。
这其中的关键点是:动态,包含两个含义:
1、按需,可以把一个包拆开来加载其中一部分;
2、运行时,跑在浏览器而非 node 编译时;
另一个 bundle 的代码,之前应用之间做共享是在文件级或 npm 包级 export 成员,现在可以在应用级 export 成员属性。
Module Federation 里有两个主要概念 host 和 remote。每个项目可以是 host 也可以是 remote,也可以两个都是。
配置 remote
webpack.config.js
src/index.js
src/bootstrap.js
src/App.js
src/NewsList.js 这个组件导出给别人使用,在 webpack 配置中可以看到。
配置 host
webpack.config.js
src/index.js
src/bootstrap.js
src/App.js 中导入了之前别人写好的 NewsList 组件,在 webpack 配置中可以看到。
A 应用可以引用 B 整个应用,也可以应用 B 的页面和组件。这样一来,灵活性就非常大了。
配置参数
${name}/${expose}
以上代码都可以在我的demo中看到:https://github.com/wuxianqiang/webacpk5-remote