@cesarchamal/single-spa-angular-app
v1.0.18
Published
Angular v8 application with two example pages for be included in a single-spa application as registered app.
Maintainers
Readme
single-spa-angular-app
Part of Demo Microfrontends - A comprehensive Single-SPA microfrontend architecture demonstration
An Angular 8 microfrontend for Single-SPA demonstrating modern Angular features, TypeScript integration, and enterprise-grade development patterns.
🏗️ Microfrontend Architecture
This application is one of 12 microfrontends in the demo-microfrontends project:
| Microfrontend | Framework | Port | Route | Repository | |---------------|-----------|------|-------|------------| | 🎯 Root App | Single-SPA | 8080 | Orchestrator | single-spa-root | | 🔐 Auth App | Vue.js | 4201 | /login | single-spa-auth-app | | 🎨 Layout App | Vue.js | 4202 | All routes | single-spa-layout-app | | 🏠 Home App | AngularJS | 4203 | / | single-spa-home-app | | 🅰️ Angular App | Angular 8 | 4204 | /angular/* | This repo | | 💚 Vue App | Vue.js 2 | 4205 | /vue/* | single-spa-vue-app | | ⚛️ React App | React 16 | 4206 | /react/* | single-spa-react-app | | 🍦 Vanilla App | ES2020+ | 4207 | /vanilla/* | single-spa-vanilla-app | | 🧩 Web Components | Lit | 4208 | /webcomponents/* | single-spa-webcomponents-app | | 📘 TypeScript App | TypeScript | 4209 | /typescript/* | single-spa-typescript-app | | 💎 jQuery App | jQuery 3.6 | 4210 | /jquery/* | single-spa-jquery-app | | 🔥 Svelte App | Svelte 3 | 4211 | /svelte/* | single-spa-svelte-app |
Main Repository: demo-microfrontends
Features
- Angular 8: Modern Angular framework with Ivy renderer
- TypeScript: Strong typing and compile-time error detection
- Angular CLI: Standard tooling and build optimization
- RxJS: Reactive programming with observables
- Angular Router: Advanced routing with lazy loading
- Dependency Injection: Hierarchical injector system
Technology Stack
- Framework: Angular 8.2.14
- Language: TypeScript 3.5.3
- Build Tool: Angular CLI 8.3.23 with custom webpack
- State Management: Angular services with RxJS
- Integration: Single-SPA Angular adapter
Development
Prerequisites
- Node.js (v18.0.0 or higher)
- npm (v8.0.0 or higher)
- Angular CLI 8.x
Installation
npm installDevelopment Server
npm start
# Runs on http://localhost:4204Build
npm run build:single-spa
# Outputs to dist/single-spa-angular-app.jsAngular Features
Component Architecture
@Component({
selector: 'app-feature',
templateUrl: './feature.component.html',
styleUrls: ['./feature.component.scss']
})
export class FeatureComponent implements OnInit {
constructor(private service: FeatureService) {}
ngOnInit(): void {
this.loadData();
}
}Service Layer
@Injectable({
providedIn: 'root'
})
export class FeatureService {
constructor(private http: HttpClient) {}
getData(): Observable<any> {
return this.http.get('/api/data');
}
}Routing Configuration
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'feature', loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule) }
];Single-SPA Integration
This microfrontend exports the required Single-SPA lifecycle functions:
export const bootstrap = singleSpaAngular.bootstrap;
export const mount = singleSpaAngular.mount;
export const unmount = singleSpaAngular.unmount;Mount Point
The application mounts to the DOM element with ID angular-app:
<div id="angular-app"></div>Route Configuration
Configured to activate on routes starting with /angular:
singleSpa.registerApplication(
'angular',
() => loadApp('single-spa-angular-app'),
showWhenPrefix(['/angular'])
);Angular Configuration
// main.single-spa.ts
import { enableProdMode, NgZone } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { Router } from '@angular/router';
import singleSpaAngular from 'single-spa-angular';
import { AppModule } from './app/app.module';
const lifecycles = singleSpaAngular({
bootstrapFunction: singleSpaProps => {
return platformBrowserDynamic().bootstrapModule(AppModule);
},
template: '<app-root />',
Router,
NgZone
});
export const bootstrap = lifecycles.bootstrap;
export const mount = lifecycles.mount;
export const unmount = lifecycles.unmount;Angular 8 Features
Ivy Renderer
- Improved bundle sizes
- Better tree-shaking
- Enhanced debugging
- Faster builds
Differential Loading
- Modern JS for modern browsers
- Legacy JS for older browsers
- Automatic polyfill management
- Optimized bundle delivery
Dynamic Imports
- Lazy loading modules
- Code splitting
- Reduced initial bundle size
- On-demand loading
Web Workers
- Background processing
- Non-blocking operations
- Performance optimization
- CPU-intensive tasks
TypeScript Integration
Strict Type Checking
interface User {
id: number;
name: string;
email: string;
roles: UserRole[];
}
class UserService {
getUsers(): Observable<User[]> {
return this.http.get<User[]>('/api/users');
}
}Decorators and Metadata
- Component decorators
- Service injection
- Route guards
- Pipe transformations
File Structure
single-spa-angular-app/
├── src/
│ ├── app/
│ │ ├── components/ # Angular components
│ │ ├── services/ # Injectable services
│ │ ├── guards/ # Route guards
│ │ ├── pipes/ # Custom pipes
│ │ ├── app.module.ts # Root module
│ │ └── app.component.ts # Root component
│ ├── environments/ # Environment configurations
│ ├── main.single-spa.ts # Single-SPA entry point
│ └── polyfills.ts # Browser polyfills
├── dist/ # Build output directory
├── angular.json # Angular CLI configuration
├── tsconfig.json # TypeScript configuration
├── extra-webpack.config.js # Custom webpack config
├── package.json # Dependencies and scripts
└── README.md # This fileCustom Webpack Configuration
Single-SPA Integration
const singleSpaAngularWebpack = require('single-spa-angular/lib/webpack').default;
module.exports = (angularWebpackConfig, options) => {
const singleSpaWebpackConfig = singleSpaAngularWebpack(angularWebpackConfig, options);
// Override output filename
singleSpaWebpackConfig.output.filename = 'single-spa-angular-app.js';
return singleSpaWebpackConfig;
};Build Optimization
- Tree shaking
- Code splitting
- Bundle analysis
- Source map generation
RxJS Integration
Reactive Patterns
@Component({...})
export class DataComponent implements OnInit, OnDestroy {
data$ = this.service.getData().pipe(
catchError(this.handleError),
takeUntil(this.destroy$)
);
private destroy$ = new Subject<void>();
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}State Management
- Observable services
- Subject-based communication
- Reactive forms
- HTTP interceptors
Performance Optimization
- Bundle Size: ~360KB (compiled)
- Tree Shaking: Unused code elimination
- Lazy Loading: Route-based code splitting
- Change Detection: OnPush strategy optimization
Testing
Unit Tests
npm run testE2E Tests
npm run e2eLinting
npm run lintBrowser Support
- Modern browsers (ES2015+)
- Differential loading for legacy browsers
- Progressive enhancement
- Polyfill management
Development Tools
Angular DevTools
- Component inspector
- Performance profiler
- Dependency injection tree
- Router visualization
TypeScript Support
- IntelliSense
- Refactoring tools
- Error detection
- Auto-completion
Contributing
- Fork the repository
- Create a feature branch
- Follow Angular style guide
- Add unit tests for new features
- Ensure TypeScript compliance
- Submit a pull request
License
MIT License - see LICENSE file for details.
Related Projects
- Angular - Platform for building mobile and desktop web applications
- TypeScript - Typed JavaScript at scale
- RxJS - Reactive Extensions for JavaScript
- Single-SPA - Microfrontend framework
- Demo Microfrontends - Complete microfrontend demo
🚀 Quick Start
Run the complete microfrontend system:
# Clone main repository
git clone https://github.com/cesarchamal/demo-microfrontends.git
cd demo-microfrontends
# Start all microfrontends
./run.sh local devRun this microfrontend individually:
npm install
npm start
# Visit http://localhost:4204Author
Cesar Francisco Chavez Maldonado - Angular 8 Microfrontend Example
