我用javascript编写了一个简单的应用程序,并使用Module Federation来完成。到目前为止,我已经将javascript和样式分离到两个单独的"apps"
├ src/
│ ├ lib/
│ │ └ myApp.js
│ ├ scss/
│ │ └ styles.scss
│ ├ index.js
│ └ styles.js
└ webpack.config.js
index.js
导入具有所有逻辑的myApp.js
,styles.js
仅导入具有所有必要样式的sass文件,如下所示:
import './scss/signing-widget.scss';
webpack.config.js
中的ModuleFederationPlugin
设置如下:
module.exports = {
entry: {
index: ['./src/index.js'],
styles: ['./src/styles.js'],
},
...
plugins: [
new ModuleFederationPlugin({
name: 'myApp',
filename: 'remoteEntry.js',
exposes: [
'./myApp': './src/index.js'
'./myAppStyles': './src/styles.js'
],
shared: [
require('./package.json').dependencies
],
})
],
...
要实现和使用myApp
,您需要做以下事情:
<html>
<head>
...
<script defer src="http://path-to-my-app/index.js"></script>
<script defer src="http://path-to-my-app/styles.css"></script>
<script defer src="http://path-to-my-app/remoteEntry.js"></script>
</head>
<body>
<my-app></my-app>
</body>
</html>
但是,我只想通过像这样导入remoteEntry.js
来实现应用程序:
<html>
<head>
...
<script defer src="http://path-to-my-app/remoteEntry.js"></script>
</head>
<body>
<my-app></my-app>
</body>
</html>
但是我不知道如何做到这一点,我做了很多研究,但我没有找到任何例子也没有文档如何实现这一点与ModuleFederationPlugin
。有人能在这件事上帮助我吗?
谢谢你,Clydefrog
我最终制作了自己的"裱花"脚本。我将把我的解决方案分享给任何觉得有趣或遇到同样问题的人。
├ src/
│ ├ lib/
│ │ └ myApp.js
│ ├ scss/
│ │ └ styles.scss
│ ├ index.js
│ ├ mount.js <------ NEW MOUNT
│ └ styles.js
└ webpack.config.js
我没有操作或更改rmeoteEntry.js
为自动导入模块,而是创建了一个简单的javascript文件(mount.js
),它检测自己的script
-标记。然后提取基本URL,然后用相同的基本URL遍历需要导入的每个文件:
mount.js
(() => {
const parseUrlString = (url) => !url || url.length <= 0 ? '' : new URL(url).origin;
var startsWith = '^',
contains = '*',
endsWith = '$',
scriptElement = document.querySelector(`script[src${endsWith}="widgetMount.js"]`),
url = parseUrlString(scriptElement?.getAttribute('src')),
head = document.getElementsByTagName('head')[0];
[
'styles.css',
'index.js',
'remoteEntry.js',
].forEach((filename) => {
var newElement;
switch (filename.split('.')[1]) {
case 'css':
newElement = document.createElement('link');
newElement.setAttribute('rel', 'stylesheet');
newElement.href = `${url}/${filename}`;
break;
case 'js':
newElement = document.createElement('script');
newElement.setAttribute('defer', '');
// newElement.setAttribute('async', '');
newElement.type = 'module';
newElement.src = `${url}/${filename}`;
break;
}
head.appendChild(newElement);
});
})();
将它添加到我的远程应用程序的webpack.config.js
:
module.exports = {
entry: {
...,
widgetMount: ['./src/mount.js'], // widget mount
...
},
...
plugins: [
new ModuleFederationPlugin({
...,
exposes: [
...,
'./myMount': './src/mount.js'
...
],
...,
})
],
...
}
最后但并非最不重要的是,将挂载添加到我的托管应用程序中:
<html>
<head>
...
<script defer src="http://path-to-my-app/widgetMount.js"></script>
</head>
<body>
<my-app></my-app>
</body>
</html>
瞧:
<html>
<head>
...
<script defer src="http://path-to-my-app/widgetMount.js"></script>
<link rel="stylesheet" href="http://path-to-my-app/styles.css">
<script defer src="http://path-to-my-app/index.js" type="module"></script>
<script defer src="http://path-to-my-app/remoteEntry.js" type="module"></script>
</head>
<body>
<my-app></my-app>
</body>
</html>