To get this working required changes to the Angular app and configuring the DevOps pipeline correctly.
The Angular app required 3 changes:
- Enable SSR
ng add @nguniversal/express-engine
- Add a wildcard route to app-routing.module.ts
const routes: Routes = [ { ... { path: "**", redirectTo: "" } ];
To ensure an App container is up and running, Azure will send requests to robots933456.txt. If that route isn’t handled the app won’t start.
- Update server.ts for Production
Replace this line in server.ts:
const distFolder = join(process.cwd(), 'dist/YOUR_APP_NAME/browser');
With:
let distFolder = join(process.cwd(), "browser");
if (!existsSync(distFolder)) {
distFolder = join(process.cwd(), "dist/YOUR_APP_NAME/browser");
}
Why? Because when you build an Angular Universal app two folders are output:
- dist/YOUR_APP_NAME/browser
- dist/YOUR_APP_NAME/server
When your app is deployed to Azure, the contents of the server folder will be at the root directory, so to make sure your local build and production build both work, the dist folder needs to be configured differently for each environment.
That’s it for the Angular changes, the rest of the work is done in Azure DevOps.
Build Pipeline steps:
npm step: install the Angular CLI on the build server
install @angular/cli -g
npm step: install node packages
npm install
Command line step: build the Angular app using SSR
npm run build:ssr
4: Copy files step: copy the server folder contents to a new dist folder
Source:
dist/YOUR_APP_NAME/server
Target:
client/YOUR_APP_NAME/deploy-dist
- Copy files step: copy the browser folder to the new dist folder
Source:
client/browser/dist/YOUR_APP_NAME/browser
Target:
client/browser/deploy-dist/browser
Steps 4 & 5 are required to have the correct folder structure.
Command line: rename main.js
rename main.js index.js
index.js is required to get express running.
Archive files step: zip the deploy-dist folder
Publish Pipeline Artifacts step: publish the zip
Release Pipeline step:
Deploy the artifact using Azure App Service deploy