Webpack 5 模块联合失败处理

标签 webpack module webpack-5 federation webpack-module-federation

所以我开始使用 webpack 5 模块联合,它在主机和微前端之间运行得很好。

但我注意到,如果微前端服务器关闭,那么在主机应用程序中,当它尝试获取 remoteEntry.js 并失败时,主机应用程序 ui 根本不会启动。

如果它是一个不可用的依赖项,这是可以理解的,但我认为更好的解决方案是有一个类似占位符的东西......而不是整个应用程序 ui 由于 Remote 损坏而拒绝启动。

有什么解决办法吗?我认为 webpack 应该对远程进行检查,如果失败,它会优雅地处理它。

如果微前端的目标是关注点分离,我认为远程 Assets 可能会阻止应用程序完全运行,这是不好的。

最佳答案

更新:

实际上有几种不同的方法来处理远程可用性:

  • Promise Based Dynamic Remotes :您可以将 promise 传递给模块联合插件配置,而不是远程的普通 url。这个 promise 和你的错误处理逻辑将在运行时得到解决。可以像该示例中那样完成:

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'
))

关于Webpack 5 模块联合失败处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68318789/

相关文章:

c++ - 子模块 : how to divide C++ module into submodules

ruby - Perl 和 Ruby 模块在同一个存储库中?

vue.js - Vue 3 和 webpack 5 - 错误 : "module property was removed from Dependency"

reactjs - 错误 : Prevent writing to file that only differs in casing or query string from already written file. reactjs laravel

node.js - 无服务器错误代码 10021 : Uncaught ReferenceError: require is not defined

webpack - 即使在生产模式下构建,VueJS 也会显示 "development mode"消息

webpack - Node js webpack 命令不起作用

webpack - 可以只显示 webpack 中的错误吗?

javascript - Node/npm : How to manage globally installed devDependencies

typescript - TsconfigPathsPlugin 类型与 webpack 5 不兼容