学习笔记 webpack模块联邦 必须项:ModuleFederationPlugin
1.引入服务
服务一(console_home)
/*
* @Description: 配置文件
* @Author: xiao di
* @Date: 2021-07-14 08:36:52
* @LastEditTime: 2022-08-27 17:34:53
*/
/**
* @file 本文件为部署不同环境等全局变量配置文件
*/
module.exports = {
auth_core: {
url: '127.0.0.1',
post: 3000
}
}
服务引入文件
/*
* @Description: 服务映射
* @Author: xiao di
* @Date: 2022-08-24 19:08:07
* @LastEditTime: 2022-08-27 17:43:34
*/
const host = require('./public/conf/app-conf.js')
const fileName = 'remoteEntry.js'
let publicPath = null
if (process.env.NODE_ENV === 'development') {
// 开发环境
publicPath = 'http://localhost' // webpack 公共路径
}
// 动态加载远程 js 文件
const useDynamicScript = (url) => {
return new Promise((resolve, reject) => {
const element = document.createElement('script')
element.src = url
element.type = 'text/javascript'
element.async = true
element.onload = (e) => {
resolve(true)
}
element.onerror = (e) => {
console.error('加载远程服务失败,具体原因', e);
reject(false)
}
document.head.appendChild(element)
})
}
// 加载组件
const loadComponent = (scope, module) => {
return async () => {
// 初始化共享作用域。使用此版本和所有远程提供的已知模块填充它
__webpack_init_sharing__('default')
const container = window[scope] // 或者到别的地方去拿容器
// 初始化容器,它可以提供共享模块
container.init(__webpack_share_scopes__.default)
const factory = await window[scope].get(module)
const Module = factory()
return Module
}
}
// 获取指定组件或者视图
export async function get(scope, module, name) {
var components = await loadComponent(scope, module)()
return components[name]
}
// 处理联邦组件所有导出项
export const moduleFederationPlugin = () => {
return new Promise(async (resolve, reject) => {
if (!window.EcRootMs) {
// 加载远程库 TODO: 后期放在 npm 包内
for (const key in host) {
await useDynamicScript(`${ (publicPath || host[key].url) + ":" + host[key].post}/${fileName}?date=${Date.now()}`) // 远程模块地址
}
window.EcRootMs = {
publicJS: false
}
}
resolve(true)
})
}
VUE加载文件(此处仅为示例,因为加载远程组件为异步加载,在使用远程库的时候必须在其加载完成)**
moduleFederationPlugin().then(() => {
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app');
})
调用方式
<template>
<div id="app">
<new-header></new-header>
<router-view />
</div>
</template>
<script>
import {get} from '../serviceName'
export default {
components:{
newHeader: () => get('auth_core', './components', 'NewHeader')
},
data() {
return {};
},
mounted () {
}
}
</script>
服务二 (auth_core)
统一抛出文件
module.exports = {
'./components': './share/components',
'./publicJS': './share/public',
'./remoRouter': './share/remoRouter',
'./views': './share/views'
}
抛出公共组件
/*
* @Description: 共享公共组件内容
* @Author: xiao di
* @Date: 2022-08-27 15:50:52
* @LastEditTime: 2022-08-27 17:14:03
*/
import NewHeader from '../src/components/Header.vue'
export {
NewHeader
}
webpack.config.js
/*
* @Description:
* @Author: xiao di
* @Date: 2021-07-13 09:43:58
* @LastEditTime: 2022-08-27 16:04:43
*/
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin');
const { ModuleFederationPlugin } = require("webpack").container;
const share = require('./share/index.js');
console.log(share);
module.exports = {
devtool: false,
entry: './src/main.js',
mode: "development",
devServer: {
port: 3000,
contentBase: path.join(__dirname, "dist"),
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
// 请确保引入这个插件!
new VueLoaderPlugin(),
new HTMLWebpackPlugin({
template: path.resolve(__dirname, './public/index.html')
}),
new ModuleFederationPlugin({
// 提供给其他服务加载的文件
filename: "remoteEntry.js",
// 唯一ID,用于标记当前服务
name: "auth_core",
library: { type: "var", name: "auth_core" },
// 需要暴露的模块,使用时通过 `${name}/${expose}` 引入
exposes: share
})
]
}