首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Webpack模块联邦不使用急切的共享库

Webpack模块联邦不使用急切的共享库
EN

Stack Overflow用户
提问于 2021-02-10 00:44:31
回答 4查看 13.9K关注 0票数 12

我正在研究Webpack 5模块的联邦功能,并遇到一些问题,为什么我的代码不能工作。这个想法与标准的模块联合示例非常相似:

app1 -是主机应用程序app2 -是向app1公开整个应用程序的遥控器

(app1呈现标题和水平线,app2应在其下方呈现)

app1app2都将reactreact-dom声明为它们在weback.config.js中共享的、单独的、迫切的依赖项

代码语言:javascript
复制
// app1 webpack.config.js
module.exports = {
  entry: path.resolve(SRC_DIR, './index.js');,
  ...
  plugins: [
    new ModuleFederationPlugin({
      name: "app1",
      remotes: {
        app2: `app2@//localhost:2002/remoteEntry.js`,
      },
      shared: { react: { singleton: true, eager: true }, "react-dom": { singleton: true, eager: true } },
    }),
    ...
  ],
};
代码语言:javascript
复制
// app2 webpack.config.js
module.exports = {
  entry: path.resolve(SRC_DIR, './index.js');,
  ...
  plugins: [
    new ModuleFederationPlugin({
      name: "app2",
      library: { type: "var", name: "app2" },
      filename: "remoteEntry.js",
      exposes: {
        "./App": "./src/App",
      },
      shared: { react: { singleton: true, eager: true }, "react-dom": { singleton: true, eager: true } },
    }),
    ...
  ],
};

在App1 index.js中,我有以下代码:

代码语言:javascript
复制
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";


ReactDOM.render(<App />, document.getElementById("root"));

接下来是App1 App.js组件:

代码语言:javascript
复制
import React, { Suspense } from 'react';

const RemoteApp2 = React.lazy(() => import("app2/App"));

export default function App() {
  return (
    <div>
      <h1>App 1</h1>
      <p>Below will be some content</p>
      <hr/>
      <Suspense fallback={'Loading App 2'}>
        <RemoteApp2 />
      </Suspense>
    </div>
  );
}

但是当我启动应用程序时,我得到了下一个错误:

代码语言:javascript
复制
Uncaught Error: Shared module is not available for eager consumption: webpack/sharing/consume/default/react/react?1bb3
    at Object.__webpack_modules__.<computed> (consumes:133)
    at __webpack_require__ (bootstrap:21)
    at fn (hot module replacement:61)
    at Module../src/index.js (main.bundle.a8d89941f5dd9a37d429.js:239)
    at __webpack_require__ (bootstrap:21)
    at startup:4
    at startup:6

如果我提取从index.jsbootstrap.jsindex.js中的所有内容,就可以了

代码语言:javascript
复制
import('./bootstrap');

一切都运行得很好。

这把我搞糊涂了,因为official docsblog posts来自创建者,他们说你可以用bootstrap.js的方式来做,也可以把依赖声明为一个迫切的依赖。

感谢任何关于为什么它没有bootstrap.js模式就不能工作的帮助/见解。

这是我正在构建的完整GitHub沙箱的链接:https://github.com/vovkvlad/webpack-module-fedaration-sandbox/tree/master/simple

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2021-03-15 08:18:25

为了使其正常工作,您需要更改加载远程条目的方式。

  1. 将app1的webpack.config.js中的ModuleFederationPlugin配置更新为:

代码语言:javascript
复制
...

new ModuleFederationPlugin({
    name: "app1",
    remoteType: 'var',
    remotes: {
      app2: 'app2',
    },
    shared: {
      ...packageJsonDeps,
      react: { singleton: true, eager: true, requiredVersion: packageJsonDeps.react },
      "react-dom": { singleton: true, eager: true, requiredVersion: packageJsonDeps["react-dom"] }
    },
}),

...

  1. Add script tag to the head of your index.html in app1 :

代码语言:javascript
复制
<script src="http://localhost:2002/remoteEntry.js"></script>

更进一步的黑客攻击,看起来不错!

更新:

为了方便起见:我为您的沙箱存储库创建了一个PR,并对上面描述的问题进行了修复:https://github.com/vovkvlad/webpack-module-fedaration-sandbox/pull/2

票数 3
EN

Stack Overflow用户

发布于 2021-03-15 21:28:30

只是为了让那些可能会错过最初答案的人清楚地知道:

它最初失败的主要原因似乎是remoteEntry.js文件是在实际运行主机应用的代码之后加载的。

bootstrap.js方法和将直接脚本<script src="http://localhost:2002/remoteEntry.js"></script>添加到<head></head>标签都有完全相同的结果-它们使remoteEntry.js在主应用程序代码之前加载和解析

在bootstrap的情况下,顺序是下一步:

加载

  1. main_bundle时,会将主要代码提取到bootstrap.js文件中- remoteEntry.js是实际运行主应用程序

的加载应用程序

使用提出的变体,事件顺序如下:

首先加载

  1. remoteEntry.js,因为它直接添加到html文件中,在加载

link

  • main_bundle并运行应用程序remoteEntry 后,会将webpack的main_bundle追加到remoteEntry中

如果只是尝试在没有引导程序的情况下运行应用程序,并且在remoteEntry.js之前加载<head></head> main_bundle中的硬编码脚本,并且当main_bundle尝试实际运行应用程序时,它会失败并返回错误:

票数 7
EN

Stack Overflow用户

发布于 2021-08-29 08:02:51

您可以在Module Federation的高级API中将依赖项设置为eager,该API不会将模块放在异步块中,但会同步提供它们。这允许我们在初始块中使用这些共享模块。但要小心,因为所有提供的和备用模块都会被下载。建议只在应用程序的某一点提供它,例如shell。

Webpack的网站强烈推荐使用异步边界。它将拆分较大块的初始化代码,以避免任何额外的往返,并在总体上提高性能。

例如,您的条目如下所示:

代码语言:javascript
复制
index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

让我们创建bootstrap.js文件,并将条目的内容移动到其中,然后将引导程序导入到条目中:

index.js

代码语言:javascript
复制
+ import('./bootstrap');
- import React from 'react';
- import ReactDOM from 'react-dom';
- import App from './App';
- ReactDOM.render(<App />, document.getElementById('root'));

bootstrap.js

代码语言:javascript
复制
+ import React from 'react';
+ import ReactDOM from 'react-dom';
+ import App from './App';
+ ReactDOM.render(<App />, document.getElementById('root'));

这种方法可以工作,但可能有局限性或缺点。

设置eager:对于通过ModuleFederationPlugin的依赖项,设置为true

webpack.config.js

代码语言:javascript
复制
// ...
new ModuleFederationPlugin({
  shared: {
    ...deps,
    react: {
      eager: true,
    },
  },
});

Source

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66123283

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档