如何将完整Angular 7应用导出为模块实现微前端集成?
Hey there! This is totally feasible, and it’s a solid approach for building Angular microfrontends while keeping separate repos and enabling parallel team development. The key here is combining Angular Module Federation (to turn your sub-app into a loadable module) with your existing Spring Gateway setup. Let’s walk through how to make this work:
Step 1: Convert Your Sub-Angular App into a Remote Module
First, you’ll need to refactor your sub-app so it can be loaded as a module by the container, instead of bootstrapping itself as an independent app. We’ll use Angular’s Module Federation for this:
Add Module Federation to the sub-app:
Run this command in your sub-app repo:ng add @angular-architects/module-federationThis generates all necessary configuration files automatically.
Update the federation config (
webpack.config.js):
Modify it to expose your sub-app’s root module as a remote entry point for the container. Example:const shareConfig = require('./src/app/shared.module-federation'); module.exports = withModuleFederationPlugin({ name: 'appOne', filename: 'remoteEntry.js', // This is the file the container will fetch to load the module exposes: { './AppModule': './src/app/app.module.ts', // Expose your sub-app's root module }, shared: { ...shareConfig.sharedMappings.getDescriptors(), // Share common Angular dependencies to avoid duplication }, });Adjust
main.tsto avoid auto-bootstrapping:
We only want the sub-app to bootstrap itself if it’s running independently (for local development). Update the file like this:import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; // Only bootstrap if we're not running as a microfrontend if (!(window as any).microFrontend) { platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.error(err)); } // Export the module so the container app can load it export { AppModule };Build and run the sub-app:
Deploy it to your target port (8081 as you mentioned) — ensure theremoteEntry.jsand all static assets are accessible at the root of this port.
Step 2: Configure the Container App to Load the Remote Module
Now update your container app to pull in the sub-app as a lazy-loaded module:
Add Module Federation to the container app:
Run the sameng add @angular-architects/module-federationcommand here too.Update the container’s federation config:
Add a reference to your sub-app’s remote entry, pointing through your Spring Gateway:const shareConfig = require('./src/app/shared.module-federation'); module.exports = withModuleFederationPlugin({ name: 'shell', remotes: { // Route through the gateway to access the sub-app's remote entry appOne: 'appOne@http://localhost:8080/appone/remoteEntry.js', }, shared: { ...shareConfig.sharedMappings.getDescriptors(), }, });Add a route for the sub-app in the container:
In your container’sapp-routing.module.ts, add a lazy-loaded route that maps to the sub-app’s module:import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; const routes: Routes = [ { path: '', component: HomeComponent }, // Lazy load the sub-app's module when users navigate to /appone { path: 'appone', loadChildren: () => import('appOne/AppModule').then(m => m.AppModule) }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Step 3: Tweak Spring Gateway for Proper Asset Routing
Your existing gateway route needs to handle both the module’s entry file and all the sub-app’s static assets. Update your route config to:
spring: cloud: gateway: routes: - id: mf-app-one uri: http://localhost:8081/ predicates: - Path=/appone/**, /appone/remoteEntry.js, /appone/**/*.js, /appone/**/*.css, /appone/**/*.html filters: # Strip the /appone/ prefix so the sub-app receives the correct asset paths - RewritePath=/appone/(?<path>.*), /$\{path}
This ensures that when the container requests /appone/remoteEntry.js, the gateway forwards it to http://localhost:8081/remoteEntry.js (where your sub-app’s asset lives).
Key Notes for Success
- Dependency Alignment: Make sure the container and sub-app use matching versions of shared Angular dependencies (like
@angular/core,@angular/common) to avoid duplicate runtime loads. - Sub-App Routing: If your sub-app has its own routes, set its
baseHrefto/appone/(inindex.htmlor via the--base-hrefbuild flag) to ensure route links work correctly within the container. - Testing Flow: Start the sub-app, gateway, and container in order. Verify that accessing
http://localhost:8080/apponeloads the sub-app as an integrated module within the container, not as a separate standalone app.
This setup keeps your sub-apps in separate repos, lets teams develop independently, and integrates them seamlessly into the container app via the gateway.
内容的提问来源于stack exchange,提问作者Bikshu s

