我正在尝试使用 Angular 13 和 React、Webpack 5 和 Module Federation 插件来实现微前端。我有一个远程 Angular 应用程序,我正在尝试将其导入到我的主机 React 应用程序中。我已遵循文档和指南,但收到错误 ScriptExternalLoadError:加载脚本失败。当尝试加载远程 Angular 应用程序时。
以下是我的实施细节:
webpack-config 角度应用程序
const path = require('path');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/bootstrap.ts',
optimization: {
splitChunks: false,
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
chunkFilename: '[id].chunk.js',
scriptType: 'text/javascript'
},
resolve: {
extensions: ['.ts', '.js'],
},
module: {
rules: [
{
test: /\.ts$/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
},
{
test: /\.html$/,
loader: 'html-loader',
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
devServer: {
static: {
directory: path.join(__dirname, 'dist'),
},
compress: true,
port: 8082,
hot: true,
historyApiFallback: true,
},
plugins : [
new ModuleFederationPlugin({
name : 'cubs',
library: { type: 'var', name: 'profile' },
filename : 'remoteEntry.js',
exposes : {
'./angular' : './src/bootstrap'
}
}),
]
};
package-json
{
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular-builders/custom-webpack": "^13.1.0",
"@angular/animations": "~13.3.0",
"@angular/common": "~13.3.0",
"@angular/compiler": "~13.3.0",
"@angular/core": "~13.3.0",
"@angular/forms": "~13.3.0",
"@angular/platform-browser": "~13.3.0",
"@angular/platform-browser-dynamic": "~13.3.0",
"@angular/router": "~13.3.0",
"clean-webpack-plugin": "^4.0.0",
"html-webpack-plugin": "^5.5.1",
"i": "^0.3.7",
"npm": "^9.6.6",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~13.3.11",
"@angular/cli": "~13.3.11",
"@angular/compiler-cli": "~13.3.0",
"@types/jasmine": "~3.10.0",
"@types/node": "^12.11.1",
"jasmine-core": "~4.0.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.1.0",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"style-loader": "^3.3.2",
"ts-loader": "^9.4.2",
"typescript": "~4.6.2"
}
}
角度.json
{
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./custom-webpack.config.js"
},
bootstrap.ts
import 'zone.js';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { AppComponent } from './app/app.component';
export function mount(container: HTMLElement, props: any) {
const appComponent = new AppComponent();
const element = appComponent.getElement();
container.appendChild(element);
console.log("Component mounted")
}
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
在我的 React 主机应用程序中 webpack-dev.config
const { merge } = require('webpack-merge')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const commonConfig = require('./webpack.common')
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
const devConfig = {
mode : 'development',
devServer : {
port : 8080,
historyApiFallback : {
index : 'index.html'
}
},
plugins : [
new ModuleFederationPlugin({
name : 'container',
remotes : {
reactapp : 'reactapp@http://localhost:8081/remoteEntry.js',
angular : "angular@http://localhost:8082/remoteEntry.js"
}
}),
new HtmlWebpackPlugin({
template : '/public/index.html'
})
]
}
module.exports = merge(commonConfig, devConfig)
App.js 中导入的 React 组件
import React, { useRef, useEffect } from 'react';
import 'angular/angular'
const AngularAppWrapper = () => {
const appRef = useRef(null);
console.log("Making an attempt")
console.log(mount);
useEffect(() => {
if (appRef.current) {
mount(appRef.current, {});
}
}, []);
return <div ref={appRef} />;
};
export default AngularAppWrapper;
主机反应Bootstrap
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
reportWebVitals();
在将 Module Federation 与 Webpack 结合使用时,我遇到了类似的 ScriptExternalLoadError 问题。对我有用的解决方案是在 Webpack 配置中将 optimization.minimize 设置为 false。这实质上禁用了构建过程中的代码最小化步骤。
具体操作方法如下:
// webpack.config.js
module.exports = {
// ...other configurations
optimization: {
minimize: false
}
};
通过这样做,您可能会注意到包的大小会增加,因为代码没有被缩小。但是,它应该可以解决您遇到的 ScriptExternalLoadError 问题。请记住,理想情况下您应该仅在调试时执行此操作,并为生产找到更永久的解决方案。
你成功了吗?我在 React 主机中使用 Angular 18 微前端时遇到了同样的问题。谢谢