在具有自定义 webpack 配置的 monorepo 中使用带有 Angular 和 React 的模块联合时出现“ScriptExternalLoadError:加载脚本失败”

问题描述 投票:0回答:2

我正在尝试使用 Angular 13 和 React、Webpack 5 和 Module Federation 插件来实现微前端。我有一个远程 Angular 应用程序,我正在尝试将其导入到我的主机 React 应用程序中。我已遵循文档和指南,但收到错误 ScriptExternalLoadError:加载脚本失败。当尝试加载远程 Angular 应用程序时。

以下是我的实施细节:

  • 我有两个独立的应用程序,一个是 Angular,一个是 React。
  • 在我的 Angular 应用程序中,我已将 @module-federation/client 包添加到我的依赖项中,并配置了 webpack.config.js 文件以公开所需的模块。

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();
  • 我已经验证了 RemoteEntry.js 文件是从 Angular 应用程序的正确 URL (http://localhost:8082/remoteEntry.js) 提供的。
  • 我尝试了网上建议的几种解决方案,例如清除缓存、使用隐身模式、检查网络日志、检查导入模块的路径。
  • 尽管如此,我仍然收到错误。我不知道还能尝试什么。有人可以帮我诊断并解决这个问题吗?
reactjs angular webpack webpack-module-federation
2个回答
0
投票

在将 Module Federation 与 Webpack 结合使用时,我遇到了类似的 ScriptExternalLoadError 问题。对我有用的解决方案是在 Webpack 配置中将 optimization.minimize 设置为 false。这实质上禁用了构建过程中的代码最小化步骤。

具体操作方法如下:

// webpack.config.js

module.exports = {
  // ...other configurations
  optimization: {
    minimize: false
  }
};

通过这样做,您可能会注意到包的大小会增加,因为代码没有被缩小。但是,它应该可以解决您遇到的 ScriptExternalLoadError 问题。请记住,理想情况下您应该仅在调试时执行此操作,并为生产找到更永久的解决方案。


0
投票

你成功了吗?我在 React 主机中使用 Angular 18 微前端时遇到了同样的问题。谢谢

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.