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
相关产品推荐
相关产品推荐

