我正在研究Webpack 5模块的联邦功能,并遇到一些问题,为什么我的代码不能工作。这个想法与标准的模块联合示例非常相似:
app1 -是主机应用程序app2 -是向app1公开整个应用程序的遥控器
(app1呈现标题和水平线,app2应在其下方呈现)
app1和app2都将react和react-dom声明为它们在weback.config.js中共享的、单独的、迫切的依赖项
// 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 } },
}),
...
],
};// 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中,我有以下代码:
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(<App />, document.getElementById("root"));接下来是App1 App.js组件:
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>
);
}但是当我启动应用程序时,我得到了下一个错误:
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.js到bootstrap.js和index.js中的所有内容,就可以了
import('./bootstrap');一切都运行得很好。
这把我搞糊涂了,因为official docs和blog posts来自创建者,他们说你可以用bootstrap.js的方式来做,也可以把依赖声明为一个迫切的依赖。
感谢任何关于为什么它没有bootstrap.js模式就不能工作的帮助/见解。
这是我正在构建的完整GitHub沙箱的链接:https://github.com/vovkvlad/webpack-module-fedaration-sandbox/tree/master/simple
发布于 2021-03-15 08:18:25
为了使其正常工作,您需要更改加载远程条目的方式。
webpack.config.js中的ModuleFederationPlugin配置更新为:...
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"] }
},
}),
...script tag to the head of your index.html in app1 :<script src="http://localhost:2002/remoteEntry.js"></script>更进一步的黑客攻击,看起来不错!
更新:
为了方便起见:我为您的沙箱存储库创建了一个PR,并对上面描述的问题进行了修复:https://github.com/vovkvlad/webpack-module-fedaration-sandbox/pull/2
发布于 2021-03-15 21:28:30
只是为了让那些可能会错过最初答案的人清楚地知道:
它最初失败的主要原因似乎是remoteEntry.js文件是在实际运行主机应用的代码之后加载的。
bootstrap.js方法和将直接脚本<script src="http://localhost:2002/remoteEntry.js"></script>添加到<head></head>标签都有完全相同的结果-它们使remoteEntry.js在主应用程序代码之前加载和解析。
在bootstrap的情况下,顺序是下一步:
加载
main_bundle时,会将主要代码提取到bootstrap.js文件中- remoteEntry.js是实际运行主应用程序的加载应用程序

使用提出的变体,事件顺序如下:
首先加载
remoteEntry.js,因为它直接添加到html文件中,在加载link
main_bundle并运行应用程序remoteEntry 后,会将webpack的main_bundle追加到remoteEntry中

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

发布于 2021-08-29 08:02:51
您可以在Module Federation的高级API中将依赖项设置为eager,该API不会将模块放在异步块中,但会同步提供它们。这允许我们在初始块中使用这些共享模块。但要小心,因为所有提供的和备用模块都会被下载。建议只在应用程序的某一点提供它,例如shell。
Webpack的网站强烈推荐使用异步边界。它将拆分较大块的初始化代码,以避免任何额外的往返,并在总体上提高性能。
例如,您的条目如下所示:
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
+ import('./bootstrap');
- import React from 'react';
- import ReactDOM from 'react-dom';
- import App from './App';
- ReactDOM.render(<App />, document.getElementById('root'));bootstrap.js
+ 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
// ...
new ModuleFederationPlugin({
shared: {
...deps,
react: {
eager: true,
},
},
});https://stackoverflow.com/questions/66123283
复制相似问题