更新:
实际上有几种不同的方法来处理遥控器的可用性:
- 基于 Promise 的动态遥控器:您可以将 Promise 传递给 Module Federation 插件配置,而不是遥控器的普通 url。这个承诺和你的错误处理逻辑将在运行时得到解决。可以像该示例中那样完成:
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
app1: `promise new Promise(resolve => {
const urlParams = new URLSearchParams(window.location.search)
const version = urlParams.get('app1VersionParam')
// This part depends on how you plan on hosting and versioning your federated modules
const remoteUrlWithVersion = 'http://localhost:3001/' + version + '/remoteEntry.js'
const script = document.createElement('script')
script.src = remoteUrlWithVersion
script.onload = () => {
// the injected script has loaded and is available on window
// we can now resolve this Promise
const proxy = {
get: (request) => window.app1.get(request),
init: (arg) => {
try {
return window.app1.init(arg)
} catch(e) {
console.log('remote container already initialized')
}
}
}
resolve(proxy)
}
// inject this script with the src set to the versioned remoteEntry.js
document.head.appendChild(script);
})
`,
},
// ...
}),
],
};
我认为模块联合插件应该用作构建时间依赖项,而不是故意包含动态模块解析和故障。
因此,在构建时很高兴知道您的应用程序中没有某些资产。
但是,如果您确实需要动态导入并在运行时使用 MF 处理端点的可用性,那么在module-federation-examples repo中有一个很好的例子
或它的简化版本:
const loadScope = (url, scope) => {
const element = document.createElement('script');
const promise = new Promise((resolve, reject) => {
element.src = url
element.type = 'text/javascript'
element.async = true
element.onload = () => resolve(window[scope])
element.onerror = reject
})`enter code here`
document.head.appendChild(element)
promise.finally(() => document.head.removeChild(element))
return promise
}
const loadModule = async (url, scope, module) => {
try {
const container = await loadScope(url, scope)
await __webpack_init_sharing__('default')
await container.init(__webpack_share_scopes__.default)
const factory = await container.get(module)
return factory()
} catch (error) {
console.error('Error loading module:', error)
throw error
}
}
const RemoteButton = React.lazy(() => loadModule(
'http://localhost:3002/remoteEntry.js',
'app2',
'./Button'
))