Appearance
Frontend Build & Deployment
This page covers how to install dependencies, run apps locally, build for each environment, and deploy to Azure.
Installation
bash
cd MFE-Apps
npm i --fForce flag is required
The --f (force) flag is mandatory due to peer dependency conflicts between Angular packages. Never run npm i without it — the install will fail or produce a broken node_modules.
Local Development
Start individual apps
bash
# Host shell (Module Federation dashboard)
nx serve apps/dashboard # http://localhost:4200
# Business Owner portal
npm run start:bussiness-owners # http://localhost:4301
# ERP modules
npm run start:erp-home # http://localhost:4401
npm run start:accounting # http://localhost:4402
npm run start:hr # http://localhost:4403
npm run start:finance # http://localhost:4404
npm run start:sales # http://localhost:4405
npm run start:purchase # http://localhost:4406
npm run start:inventory # http://localhost:4407
npm run start:distribution # http://localhost:4408
npm run start:fixed-assets # http://localhost:4409Start groups
bash
npm run start:erp # Starts all ERP apps (ports 4401-4409) in parallel
npm run start:all # Starts ALL apps including bussinessOwnersRun only what you need
You do not need to run all apps simultaneously. Keycloak SSO automatically handles authentication when you switch between apps on different ports. Just run the specific app you are developing.
Building
Single app builds
bash
# Production (default)
npm run build:apps-accounting
npm run build:apps-hr
npm run build:erp-home
npm run build:apps-sales
npm run build:apps-finance
npm run build:apps-inventory
npm run build:app-distribution
npm run build:fixed-assets
npm run build:apps-purchase
npm run build:bussiness-owners
npm run build:templates
npm run build:dashboard
# Cloud configuration
npm run build:cloud:apps-accounting
npm run build:cloud:bussiness-owners
# ... same pattern for all appsParallel build all apps
bash
# All apps — production config
npm run build:all
# All apps — cloud config
npm run build:all:cloud
# All apps — UAT config
npm run build:all:uat
# All apps — pre-production config
npm run build:all:preprod
# All apps — prod config
npm run build:all:prodParallel build command
build:all runs 11+ apps in parallel with 7 max concurrent processes:
bash
cross-env NODE_OPTIONS=--max-old-space-size=32768 concurrently --max-processes 7 \
"npm run build:dashboard" \
"npm run build:bussiness-owners" \
"npm run build:apps-inventory" \
"npm run build:apps-hr" \
"npm run build:erp-home" \
"npm run build:apps-sales" \
"npm run build:apps-finance" \
"npm run build:apps-purchase" \
"npm run build:apps-accounting" \
"npm run build:app-distribution" \
"npm run build:fixed-assets" \
"npm run publishAssets"Build Configurations
Each build configuration changes API base URLs and Keycloak realm URLs:
| Configuration | --configuration= flag | When to Use |
|---|---|---|
production | production | Default local/dev builds |
cloud | cloud | Azure cloud deployment (non-prod) |
uat | uat | UAT environment |
preprod | preprod | Pre-production environment |
prod | prod | Production environment |
Environment files are at apps/<app>/src/environments/:
environments/
├── environment.ts # Default (production config)
├── environment.development.ts # Local development
├── environment.cloud.ts # Cloud
├── environment.uat.ts # UAT
├── environment.preprod.ts # Pre-production
└── environment.prod.ts # ProductionKey values that differ per config:
typescript
export const environment = {
production: true,
isDevelopment: false,
apiBaseUrl: 'https://gateway.onlinemicrotec.com.sa',
keycloakUrl: 'https://keycloak.onlinemicrotec.com.sa',
keycloakRealm: 'microtec',
keycloakClientId: 'angular',
};Build Output
bash
dist/
├── dashboard/ # Host shell static files
├── bussinessOwners/ # BO portal static files
├── accounting/ # Accounting module static files
└── ... # One folder per appEach app's dist folder contains:
index.html- Hashed JS/CSS bundles (
output-hashing=all) web.configfor IIS/Azure hosting rules- Assets (fonts, images, i18n files)
Shared Assets Publishing
After all app builds complete, publishAssets runs automatically as the last step:
bash
npm run publishAssetsThis copies shared translation files and assets from libs/shared-assets/ into each app's dist folder. It runs node ./publish_assets.js.
Azure Deployment
ERP Apps — Azure Blob Storage
All ERP apps (dashboard + remotes except bussinessOwners) are deployed to an Azure Blob Storage account with static website hosting enabled:
| Environment | Storage Account | Container |
|---|---|---|
| dev | micerpfrdevsa | $web |
| stage | micerpfrstagesa | $web |
| preprod | micerpfrpreprodsa | $web |
| uat | micerpfruatsa | $web |
| production | micerpfrprodsa | $web |
Deployment uploads the dist folder to the $web container using az storage blob upload-batch.
Business Owners — Azure Static Web Apps
The bussinessOwners app is deployed separately to an Azure Static Web App (SWA):
- Provides SWA-specific routing rules (
staticwebapp.config.json) - Supports custom authentication providers if needed
- CDN is automatically managed by Azure SWA
Azure DevOps Pipeline
The frontend pipeline is defined at:
Devops/azure/pipelines/frontApps/deploy/unified-frontend-pipeline.ymlPipeline stages:
Branch-to-environment mapping:
| Branch | Environment |
|---|---|
main / master / production | Production |
stage / staging | Stage |
PreProd / preprod | Pre-production |
| All others | Dev |
Testing
bash
# Test all projects
nx run-many --target=test --all
# Test specific project
nx test accounting
# Test with coverage
nx test accounting --codeCoverage
# Test affected projects only (CI)
nx affected:testCode Quality
bash
# Lint all projects
nx run-many --target=lint --all
# Lint specific project
nx lint accounting
# Check affected projects
nx affected:lintTroubleshooting
Build runs out of memory
bash
# Increase Node.js heap limit manually
export NODE_OPTIONS=--max-old-space-size=32768
npm run build:allModule Federation remote not loading
- Ensure the remote app is running on its expected port.
- Check
apps/dashboard/webpack.config.js— verify the remote entry URL matches. - In production, verify the CDN routing rules forward the correct path prefixes.
Keycloak login loop
- Verify
keycloakUrlandkeycloakRealmin the environment file. - Ensure the Keycloak client has the app's origin in its "Valid Redirect URIs".
- Check that
isDevelopmentis set correctly in the environment file.