You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular模块联邦:保留远程模块base-href解决资源路径问题

解决模块联邦加载远程应用时base-href资源路径错误的问题

下面是几种可行的方案,按需选择:

方案1:动态切换base标签的href值

远程模块加载时,临时把壳应用的base href改成远程应用的,用完再切回去。

  • 在app1的app1.module.ts里导出自己的base-href:
    export const APP1_BASE_HREF = '/app1';
    
  • 壳应用里写个服务来处理base href的切换:
    import { DOCUMENT } from '@angular/common';
    import { Inject, Injectable } from '@angular/core';
    import { APP1_BASE_HREF } from 'app1/App1Module';
    
    @Injectable()
    export class RemoteLoaderService {
      private originalBase: string;
    
      constructor(@Inject(DOCUMENT) private doc: Document) {
        this.originalBase = this.doc.querySelector('base')?.getAttribute('href') || '/myapp';
      }
    
      async loadApp1() {
        // 加载远程模块
        const remoteMod = await import('app1/App1Module');
        // 切换base href到app1的路径
        this.doc.querySelector('base')?.setAttribute('href', APP1_BASE_HREF);
        return remoteMod.App1Module;
      }
    
      resetBase() {
        // 用完切回壳应用的base href
        this.doc.querySelector('base')?.setAttribute('href', this.originalBase);
      }
    }
    
  • 注意在卸载App1组件的时候调用resetBase(),别影响其他模块。

方案2:把远程组件的资源请求改成绝对路径

直接在app1的组件里,把相对路径拼接成基于自身base-href的绝对路径,不管在哪加载都能指向正确资源。

  • 用APP_BASE_HREF注入自身的base路径,然后拼接资源地址:
    import { Component, OnInit } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { APP_BASE_HREF } from '@angular/common';
    
    @Component({
      selector: 'app-app1',
      templateUrl: './app1.component.html'
    })
    export class App1Component implements OnInit {
      constructor(
        private http: HttpClient,
        @Inject(APP_BASE_HREF) private baseHref: string
      ) {}
    
      ngOnInit() {
        // 拼成绝对路径请求资源
        this.http.get(`${this.baseHref}/assets/config.json`).subscribe(config => {
          console.log('配置加载成功:', config);
        });
      }
    }
    

这种方法最直接,不需要壳应用做额外处理。

方案3:通过模块联邦配置传递base-href元数据

在app1的webpack模块联邦配置里加自定义元数据,壳应用加载远程入口时读取这个数据,用来调整路径。

  • app1的webpack.config.js里修改模块联邦配置:
    new ModuleFederationPlugin({
      name: 'app1',
      filename: 'remoteEntry.js',
      exposes: { './App1Module': './src/app/app1.module.ts' },
      shared: { ...sharedMappings.getDescriptors() },
      // 把base-href放进额外配置里
      extraOptions: { baseHref: '/app1' },
      library: { type: 'var', name: 'app1' }
    })
    
  • 壳应用里加载remoteEntry后读取元数据:
    async loadApp1() {
      const script = document.createElement('script');
      script.src = '/app1/remoteEntry.js';
      await new Promise((res, rej) => {
        script.onload = res;
        script.onerror = rej;
        document.body.appendChild(script);
      });
      // 拿到app1的base-href
      const app1Base = (window as any).app1.extraOptions.baseHref;
      // 接下来要么用方案1切换base,要么给组件传这个路径用来拼接请求
    }
    

方案4:用代理规则重定向请求

在壳应用的代理配置里加规则,把指向/app1/assets/的请求转发到远程app1的资源地址。

  • 新建proxy.conf.json:
    {
      "/app1/assets/*": {
        "target": "http://your-deployment-domain/app1",
        "secure": false,
        "pathRewrite": { "^/app1/assets": "/assets" },
        "changeOrigin": true
      }
    }
    
  • 启动壳应用时指定代理:ng serve --proxy-config proxy.conf.json
    这种适合不想改代码的场景,但要确保所有远程资源路径都被代理规则覆盖。

内容的提问来源于stack exchange,提问作者Karthik Prasad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:24:57