webpack5新增的ModuleFederationPlugin
- 一种解决微前端的解决方案,
- 共用组件升级时,避免所有依赖项目都要进行升级的痛点
remote远程组件
该项目代表的是被远程引用的共用组件库
安装项目依赖
// webpack相关yarn add webpack webpack-cli webpack-dev-server html-webpack-plugin -D// 框架类相关yarn add react react-dom babel-loader @babel/core @babel/preset-react -D
设置webpack.config.js
const path = require("path");const webpack = require("webpack");const htmlWebpackPlugin = require("html-webpack-plugin");const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");module.exports = {mode: "development",entry: "./src/index.js",output: {publicPath: "http://localhost:3000/",},devtool: false,devServer: {port: 3000,},module: {rules: [{test: /\.jsx?$/,use: {loader: "babel-loader",options: {presets: ["@babel/preset-react"],},},exclude: /node_modules/,},],},plugins: [new htmlWebpackPlugin({template: "./public/index.html",}),// 定义被引用时的名称,引入路径 ${name}/${exposes} -> remote/NewListnew ModuleFederationPlugin({name: "remote",filename: "remoteEntry.js",// 提供组件时:exposesexposes: {"./NewList": "./src/NewList",},// 性能优化shared: {react: { singleton: true },"react-dom": { singleton: true },},}),],};
组件中目录代码
├── package.json├── public│ └── index.html├── src│ ├── App.js│ ├── NewList.js│ ├── bootstrap.js│ └── index.js├── webpack.config.js
package.json
"scripts": {"start": "webpack serve","build": "webpack"},
index.js
import "./bootstrap";
App.js
import React from "react";import NewList from "./NewList";export default (props) => {return (<div><h1>App</h1><hr /><h3>list</h3><NewListlist={[{ id: 1, name: "js" },{ id: 2, name: "webpack" },]}/></div>);};
bootstrap.js
import React from "react";import { createRoot } from 'react-dom/client';import App from "./App";const root = createRoot(document.getElementById("app"));root.render(<App />);
NewList.js
import React from "react";export default (props) => {return (<ol>{props.list && props.list.map((l) => <li key={l.id}>{l.name}</li>)}</ol>);};
生成了remoteEntry.js
启动项目是会发现生成了remoteEntry.js文件,该文件就是供其它项目引入插件时使用。
该文件会提供组件的入口链接。
host项目
安装项目依赖
// webpack相关yarn add webpack webpack-cli webpack-dev-server html-webpack-plugin -D// 框架类相关yarn add react react-dom babel-loader @babel/core @babel/preset-react -D
设置webpack.config.js
const path = require("path");const webpack = require("webpack");const htmlWebpackPlugin = require("html-webpack-plugin");const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");module.exports = {mode: "development",entry: "./src/index.js",output: {publicPath: "http://localhost:8000/",},devServer: {port: 8000,},module: {rules: [{test: /\.jsx?$/,use: {loader: "babel-loader",options: {presets: ["@babel/preset-react"],},},exclude: /node_modules/,},],},plugins: [new htmlWebpackPlugin({template: "./public/index.html",}),new ModuleFederationPlugin({name: "host",//使用的时:为remotesremotes: {remote: "remote@http://localhost:3000/remoteEntry.js",}}),],};
本地项目中目录结构
.├── package.json├── public│ └── index.html├── src│ ├── App.js│ ├── bootstrap.js│ └── index.js└── webpack.config.js
index.js
import "./bootstrap";
bootstrap.js
import React from "react";import { createRoot } from 'react-dom/client';import App from "./App";const root = createRoot(document.getElementById("app"));root.render(<App />);
App.js
import React from "react";// import 远程组件const RemoteNewList = React.lazy(() => import("remote/NewList"));export default (props) => {return (<div><h1>Remote List</h1><React.Suspense fallback="loading"><RemoteNewList list={[{ id: 1, name: "remote js" },{ id: 2, name: "remote webpack" },]} /></React.Suspense></div>);};

