基础应用代码安装css
// webpack5
npm install webpack webpack-cli html-webpack-plugin css-loader style-loader babel-loader @babel/core @babel/preset-env @babel/preset-react webpack-dev-server -D
npm install react react-dom
复制代码
基础代码:html
// ======insex.html========
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RootReact</title>
</head>
<body>
<!-- 加一行注释 -->
<div id="root"></div>
</body>
</html>
复制代码
// ======insex.js========
import React from "react"
import ReactDom from "react-dom"
import App from "./App"
ReactDom.render(<App/>,document.getElementById('root'))
// ======App.js===========
import React from "react"
import User from "./User"
let App = () => {
return (
<div> <h3>webpack55</h3> <User/> </div>
)
}
export default App;
// ===== User.js==========
import React from "react"
const User = ()=>{
return (
<div> UserList </div>
)
}
export default User
复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// entry 入口,output出口,module模块,plugins 插件 mode工做模式,devServer开发服务器
// mode 工做模式
mode: 'development', // production 、 development、none
// 入口
entry: './src/index.js',
// 出口
output: {
filename: './bundle.js',
path: path.resolve(__dirname, 'dist')
},
// 模块
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react'
]
}
}
]
},
]
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
// 服务器
devServer: {
contentBase: path.join(__dirname, 'dist'),
port: 3000,
open: true
},
}
复制代码
package.json 启动命令:前端
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build":"webpack",
"start":"webpack serve"
},
复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 导入模块联邦插件
const Mfp = require('webpack').container.ModuleFederationPlugin;
^^^^^^^^Codes^^^^^^^^^^^^^
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
// 实例化模块联邦插件
new Mfp({
// 对外提供的打包后的文件名,引入时使用
filename:'myuser.js',
// 微应用(模块) 名称,相似 single-spa的团队名字
name:'study',
exposes:{
// 具体的一个文件能够看成一个模块应用,
// 每个应用都有一个名字和具体指定的代码文件
// 名字:具体打包的代码文件
'./xx':'./src/User.js',
'./goods':'./src/Goods.js'
}
})
],
复制代码
const Mfp = require('webpack').container.ModuleFederationPlugin
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new Mfp({
// // 微应用(模块) 名称,当前模块本身的名字
name:'roots',
// 导入模块
remotes:{
// 导入后给模块起个别名:"微应用名称@地址/导出的文件名"
one:"study@http://localhost:3001/myuser.js"
}
})
],
复制代码
在组件中使用vue
// const xx = React.lazy(()=>import("导入时模块别名/导出时具体文件对应的名字"))
const Us = React.lazy(()=>import("one/xx"))
const Gos = React.lazy(()=>import("one/goods"))
let App = () => {
return (
<div> <h3>webpack5 root</h3> <User/> <React.Suspense fallback="Loading app"> <Us /> <Gos /> </React.Suspense> </div>
)
}
export default App;
复制代码
完整代码示例:modulefederationvue3: 基于模块联邦实现的 Vue3.0 微前端架构示例 (gitee.com)node
package.jsonreact
{
"name": "@vue3-demo/layout",
"private": true,
"version": "1.0.0",
"scripts": {
"start": "webpack serve",
"serve": "serve dist -p 3001",
"build": "webpack --mode production",
"clean": "rm -rf dist"
},
"dependencies": {
"@babel/core": "^7.13.16",
"babel-loader": "^8.2.2",
"serve": "^11.3.2",
"vue": "^3.0.0-rc.5",
"vue-router": "^4.0.0",
"vuex": "^4.0.0"
},
"devDependencies": {
"@vue/compiler-sfc": "3.0.0",
"css-loader": "5.2.4",
"file-loader": "6.2.0",
"html-webpack-plugin": "5.3.1",
"mini-css-extract-plugin": "0.9.0",
"url-loader": "4.1.1",
"vue-loader": "16.0.0-beta.8",
"webpack": "5.35.0",
"webpack-dev-server": "3.11.2",
"webpack-cli": "4.6.0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2"
}
}
复制代码
home\webpack.config.jswebpack
const { ModuleFederationPlugin } = require("webpack").container;
module.exports = (env = {}) => ({
^^^^^^^………………^^^^^^^^^^^
plugins: [
new VueLoaderPlugin(),
// 模块联邦
new ModuleFederationPlugin({
name: "home",
filename: "remoteEntry.js",
// 导出
exposes: {
"./User": "./src/components/User",
// "./Button": "./src/components/Button",
},
}),
]
});
复制代码
layout\webpack.config.jsgit
const { ModuleFederationPlugin } = require("webpack").container;
…………
module.exports = (env = {}) => ({
plugins: [
…………
new ModuleFederationPlugin({
name: "layout",
filename: "remoteEntry.js",
// 导入
remotes: {
importUser: "home@http://localhost:3002/remoteEntry.js",
},
exposes: {},
}),
]
});
复制代码
layout\src\views\About.vueweb
<template>
<div class="about">
永远记得 西岭老湿 爱你
<hr>
<p>开启home应用的3002端口应用可见,模块联邦内容</p>
<User />
</div>
</template>
<script>
import { defineAsyncComponent } from "vue";
// 导入模块联邦组件
const User = defineAsyncComponent(() => import("importUser/User"));
export default {
components: {
User
}
};
</script>
复制代码
写好基础代码及对应配置后,分别启动 home 及 layout 两个应用项目就能够在 layout 应用的 about 中看到 home 应用中的 User 组件的内容了;vue-router