Tutorials Logic, IN info@tutorialslogic.com

Angular Deployment Build Host Your App

Choose the Deployment Model

An Angular deployment combines a production build, correct base paths, server fallback rules, cache headers, environment configuration, and post-deploy verification. A successful local build is only the beginning of release confidence.

Start with the rendering contract, because it decides what must run in production. A client-rendered application needs only static browser files, a prerendered application needs generated HTML for every known route, and an SSR or hybrid application also needs a request-time runtime.

Do not place secrets in environment files compiled into a browser bundle. Every value shipped to the browser can be inspected. Keep credentials and privileged operations on a server and provide only public configuration to Angular.

  • Static client-rendered app: publish browser assets to a static server or CDN and configure SPA fallback.
  • SSR app: deploy the generated server runtime plus browser assets to a compatible server environment.
  • Prerendered app: publish generated HTML and assets, while confirming every intended route was generated.
  • Hybrid app: deploy both browser and server outputs, then test at least one route from every configured RenderMode.
  • Decision rule: use static hosting when every request can be satisfied by files plus APIs elsewhere; use a runtime only when a route must render per request.

Production Build

ng build invokes the workspace build target and uses the production configuration by default unless the project changes that default. The application builder compiles TypeScript and templates, bundles dependencies, minifies output, removes dead code, and emits the configured outputPath under dist by default.

Read the build summary instead of assuming the output directory. Fail continuous integration on compilation errors and configured size budgets. Investigate CommonJS warnings because those dependencies can reduce bundle optimization.

Build check Release question
Output path Which directory must the host publish?
Initial bundle budget Did startup JavaScript and CSS remain within the agreed limit?
Lazy bundle budget Did one feature unexpectedly pull a large dependency?
Source maps Are production maps disabled, private, or uploaded only to the intended monitoring service?
Browser targets Does the Browserslist configuration match supported Angular browsers?
  • Run tests and ng build from a clean lockfile install; do not deploy the development server created by ng serve.
  • Read outputPath and the selected builder in angular.json. With the application builder, a static host commonly publishes the browser subdirectory inside dist/<project>.
  • Open the emitted index.html and verify its base href, script URLs, styles, icons, and public configuration before uploading anything.
  • Treat budget errors as release failures. Compare initial and lazy bundle sizes with the previous release instead of accepting unexplained growth.

Production Build Example

Production Build Example
# Build the default production configuration
ng build

# Build a named configuration when angular.json defines one
ng build --configuration staging

A named configuration can replace files and override build options. It is configuration selection, not a secure place for browser secrets.

Static Hosting Contract

All static hosts need the same three inputs: a build command, the exact directory containing index.html, and a fallback rule for Angular routes. Provider auto-detection is convenient, but the release owner should still verify those values against angular.json and the emitted dist tree.

A fallback is a rewrite, not a redirect. The browser must keep /orders/42 in the address bar while the host serves index.html, allowing the Angular router to interpret the URL. Real assets and API paths must be checked before the catch-all rule so a missing JavaScript file does not receive HTML with status 200.

  • Build command: npm run build, backed by an explicit production script in package.json.
  • Publish directory: the emitted directory that directly contains index.html, commonly dist/<project>/browser for the application builder.
  • SPA fallback: rewrite unknown application routes to /index.html with status 200, after specific redirects, APIs, and existing files.
  • Custom domain: attach the domain, verify DNS and managed TLS, then redirect one canonical host such as www to the apex or the reverse.
  • Headers: keep HTML revalidated, cache fingerprinted assets as immutable, and apply CSP and other security headers at the host.

Static Host Release Check

Static Host Release Check
# Build the same command used by the host
npm ci
npm run build

# Confirm index.html is inside the directory you plan to publish
# Replace storefront with the Angular project name
ls dist/storefront/browser

If index.html is one directory deeper than the configured publish directory, the host may show a blank listing, a provider 404, or an unrelated default page.

GitHub Pages

A project site hosted below a repository path needs a matching base href so router links, scripts, styles, and lazy chunks resolve below that path. For a repository named shop, build with /shop/ rather than /.

GitHub Pages is static hosting. Choose a workflow or Pages deployment tool that publishes the actual browser output directory. Configure a 404 fallback compatible with client-side routes, or use a hash-based URL strategy when the host cannot rewrite deep links.

  • Set Pages to deploy from a GitHub Actions workflow, then build from the lockfile with the repository subpath as base href.
  • Upload only the generated browser directory as the Pages artifact; never publish src, node_modules, or the workspace root.
  • For PathLocationStrategy, add a suitable 404 fallback copy of index.html in the published artifact. Otherwise use HashLocationStrategy so refreshes never require a server rewrite.
  • After the workflow completes, open /shop/, load a lazy feature, refresh its nested URL, and inspect the network panel for root-relative asset requests.

GitHub Pages Build

GitHub Pages Build
# Replace shop with the repository name
ng build --base-href /shop/

Publish the generated browser artifacts reported by the build. Test the site root, a lazy route, and a direct refresh of a nested URL after deployment.

GitHub Pages Workflow

GitHub Pages Workflow
name: Deploy Angular to Pages
on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: npx ng build --base-href /storefront/
      - uses: actions/configure-pages@v5
      - uses: actions/upload-pages-artifact@v4
        with:
          path: dist/storefront/browser

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy
        id: deployment
        uses: actions/deploy-pages@v4

In repository Settings > Pages, select GitHub Actions as the source. Replace storefront in both the base href and artifact path; a user or organization site hosted at the domain root uses / as its base href.

Netlify and Vercel

Both platforms can import a Git repository, detect Angular, create a preview for each pull request, and promote a production branch. Detection does not remove the need to verify the build command, project root in a monorepo, publish directory, Node version, environment variables, and router behavior.

  • Netlify: import the repository, select npm run build, and confirm the publish directory that directly contains index.html.
  • Netlify CSR: put the SPA rule in src/_redirects and include that file in the angular.json assets array, or define the equivalent rule in netlify.toml.
  • Netlify SSR: use its Angular integration rather than a blanket static rewrite, because SSR requests are handled by the generated runtime before static redirects.
  • Vercel: import the repository or run vercel, confirm Angular framework detection, then review the detected build and output settings before the production deploy.
  • On either host, add public build variables separately for preview and production. Changing a browser variable requires a new build; secret server variables must never enter the browser bundle.
  • Promote only after the preview passes nested-route refreshes, authentication callbacks, API calls, lazy chunks, and browser-console checks.

Netlify CSR Configuration

Netlify CSR Configuration
[build]
  command = "npm run build"
  publish = "dist/storefront/browser"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

Replace storefront with the project output. This catch-all belongs to a client-rendered build; an SSR integration needs its runtime route handling instead.

Vercel Git or CLI Flow

Vercel Git or CLI Flow
# Git flow: import the repository in the Vercel dashboard
# CLI flow: authenticate, create a preview, then deploy production
vercel
vercel --prod

Inspect the preview URL before --prod. If auto-detection selects the wrong root or output in a monorepo, correct the project settings rather than moving build artifacts by hand.

Firebase and Cloudflare Pages

Use Firebase Hosting or Cloudflare Pages for browser-only and fully static output. Firebase App Hosting is the appropriate Firebase path when an Angular application needs a managed server-rendered runtime; classic Hosting remains a static-file service unless explicitly connected to dynamic backends.

  • Firebase Hosting: build first, run firebase init hosting, choose the emitted browser directory as public, answer yes to the single-page-app rewrite, and review the generated files.
  • Use firebase emulators:start to test routing and headers locally, then deploy only hosting with firebase deploy --only hosting.
  • Use project aliases for staging and production so a local command cannot silently publish to the wrong Firebase project.
  • Cloudflare Pages: connect GitHub or GitLab, set the production branch, use npm run build, and set the build directory to the folder that directly contains index.html.
  • For current Angular application-builder output, Cloudflare commonly needs dist/<project>/browser. Confirm this from the build because outputPath is configurable.
  • Check a pull-request preview before production, then verify redirects, headers, custom domain, TLS, and rollback availability in the platform dashboard.

Firebase Hosting Configuration

Firebase Hosting Configuration
{
  "hosting": {
    "public": "dist/storefront/browser",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      { "source": "**", "destination": "/index.html" }
    ]
  }
}

The rewrite supports Angular deep links. Keep API or function rewrites above this catch-all so they are not swallowed by index.html.

AWS Amplify and Azure Static Web Apps

AWS Amplify Hosting and Azure Static Web Apps both provide repository-driven static deployments, preview environments, managed TLS, and CDN delivery. Their setup screens use different names, but the contract remains build command plus browser output plus SPA fallback.

  • AWS Amplify: connect the repository and branch, review the generated build specification, and set artifacts.baseDirectory to the directory containing index.html.
  • Add an Amplify 200 rewrite from /<*> to /index.html for a CSR application. Confirm that more specific redirects and reverse proxies appear before it.
  • Use Amplify branch deployments for staging and pull-request previews; test the preview before mapping the production branch to the custom domain.
  • Azure Static Web Apps: create the resource from the repository, select Angular, leave API location empty for a frontend-only app, and set output location to dist/<project>/browser for modern application-builder output.
  • Keep staticwebapp.config.json in the deployed assets and configure navigationFallback to rewrite application routes to /index.html.
  • Inspect the generated GitHub Actions or Azure DevOps workflow. A green workflow is not enough if app_location or output_location points at the wrong directory.

AWS Amplify Build Specification

AWS Amplify Build Specification
version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm ci
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: dist/storefront/browser
    files:
      - "**/*"
  cache:
    paths:
      - node_modules/**/*

Change the base directory to the actual Angular output. Configure the SPA rewrite in Amplify Hosting after this build specification is working.

Azure SPA Fallback

Azure SPA Fallback
{
  "navigationFallback": {
    "rewrite": "/index.html",
    "exclude": ["/assets/*", "/*.css", "/*.js", "/*.map"]
  }
}

Place staticwebapp.config.json where it is copied into the build output. Exclusions preserve genuine missing-file responses instead of returning HTML for asset requests.

Docker and Nginx

A container is useful when the team needs a portable image, explicit web-server rules, or deployment to a container platform. Build Angular in one stage and copy only the browser artifacts into a small Nginx image; do not ship the compiler, source tree, or node_modules in the runtime layer.

  • Pin a Node version compatible with the project and use npm ci so the container follows the lockfile.
  • Copy package files before source files to preserve the dependency layer when application code changes.
  • Serve existing files directly, use try_files for Angular routes, and return a real 404 for missing assets where possible.
  • Expose a health endpoint at the platform or proxy layer, run the image as a non-root user when the target permits it, and scan the final image.
  • Build once, tag the image with the commit SHA, deploy that immutable tag, and keep the previous tag ready for rollback.

Multi-Stage Angular Image

Multi-Stage Angular Image
FROM node:24-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist/storefront/browser /usr/share/nginx/html
EXPOSE 80

Replace storefront with the project name and pin image digests in a controlled production pipeline. The runtime image contains only Nginx configuration and deployable files.

Nginx Router Fallback

Nginx Router Fallback
server {
  listen 80;
  root /usr/share/nginx/html;
  index index.html;

  location /assets/ {
    try_files $uri =404;
  }

  location / {
    try_files $uri $uri/ /index.html;
  }
}

The asset location returns a real 404, while application routes fall back to index.html. Add cache and security headers according to the production edge architecture.

Deployment Verification

A deployment is not complete when upload succeeds. Open the production URL in a clean browser session, inspect network and console errors, test a direct deep-link refresh, verify API origins and CORS, and run one critical user journey.

Use immutable long-lived caching for fingerprinted assets, but keep the HTML shell short-lived or revalidated so it can point to the newest filenames. Retain the previous release artifacts and configuration until the new version passes smoke checks.

  • Refresh a nested route such as /users/42; a static host must return index.html for an unknown application route.
  • Request a real missing asset and confirm it remains a 404 rather than returning index.html with the wrong content type.
  • Verify authentication redirects, API base URLs, CORS, Content Security Policy, and error monitoring in the production origin.
  • Record the commit, build identifier, deployment time, migration status, and rollback command or host action.

SSR and Hybrid Deployment

Deploy the artifacts produced by the selected render mode. A client-rendered route needs browser assets and fallback routing, a server-rendered route needs a compatible request-time server runtime, and a prerendered route needs every expected HTML path generated during the build.

For an existing application, ng add @angular/ssr adds the server entry and rendering configuration. Angular can also emit a fully static application by setting outputMode to static; that build does not require a Node.js server. Do not deploy a server bundle to a static-only host and expect request-time rendering.

Mode Deployment contract
RenderMode.Client Serve browser assets and return the application shell for valid client routes that are not real files or APIs.
RenderMode.Server Run the generated server bundle, forward requests through a supported runtime, and deploy browser assets beside it.
RenderMode.Prerender Publish generated HTML plus assets and rebuild when route content or prerender parameters change.
Hybrid routes Deploy both server and browser outputs and verify each route uses its configured render mode.
Hydration Serve server-generated HTML consistently and enable client hydration without DOM rewrites that cause mismatches.
  • Test browser-only APIs behind a platform boundary so SSR does not access window, document, localStorage, or layout APIs during server rendering.
  • Verify canonical URLs, status codes, redirects, and per-route headers for server or prerendered pages.
  • Monitor server latency and failure rates separately from browser asset and API failures.
  • Run the production server artifact locally with production-like variables, then verify HTML source, hydration, status codes, redirects, cookies, and direct requests before publishing.
  • On a managed platform, use its current Angular adapter or runtime integration. On a self-managed Node host, place the process behind TLS, forward the platform port, add health checks, and shut down gracefully.
  • Scale from measured render latency and memory. Keep user-specific HTML private and never cache authenticated SSR responses at a shared edge.

Fully Static Hybrid Build

Fully Static Hybrid Build
{
  "projects": {
    "storefront": {
      "architect": {
        "build": {
          "options": {
            "outputMode": "static"
          }
        }
      }
    }
  }
}

Static output prerenders configured routes without generating a request-time Node server. Confirm parameterized routes and their fallback behavior before choosing this mode.

Caching and Configuration

A release can contain correct code and still fail because HTML, hashed assets, API endpoints, or runtime configuration are cached with the wrong policy. Treat cache headers and public configuration as versioned deployment inputs.

Artifact Recommended handling
Hashed JavaScript and CSS Cache for a long time with immutable because a content change creates a new filename.
index.html or route HTML Revalidate or use a short lifetime so it references the current hashed assets.
Service worker manifest Deploy atomically with its matching assets and test update behavior across an existing browser session.
Public runtime configuration Version and validate values such as API origin; never place credentials or signing material in it.
Source maps Keep private or upload directly to the intended monitoring service when production debugging requires them.

CI/CD and Rollback

A repeatable pipeline should build once, test the exact artifact, publish it atomically, verify the deployed origin, and preserve a fast rollback. Rebuilding separately for each environment makes artifact identity and incident diagnosis harder.

  • Install from the lockfile and record the Node.js, Angular CLI, and package versions used by the build.
  • Run linting, unit tests, production compilation, configured budgets, and a focused security scan before publishing.
  • Promote one immutable artifact and inject only public environment-specific configuration through a reviewed mechanism.
  • Use a staging or preview URL to test deep links, authentication, API calls, lazy chunks, SSR or hydration, and browser headers.
  • Publish atomically, run post-deploy smoke checks, and automatically stop or roll back when critical checks fail.
  • Retain the previous artifact and document the host-specific rollback action before the release starts.

Deployment Troubleshooting

Diagnose production failures from the first incorrect layer: DNS and TLS, host routing, HTML, static assets, Angular bootstrap, API traffic, then SSR or hydration. Repeatedly rebuilding without identifying that layer can hide the symptom while preserving the faulty configuration.

Symptom Likely cause and check
Provider 404 at the site root The publish directory is wrong. Point it at the folder that directly contains the emitted index.html.
Home works; nested refresh is 404 The CSR fallback is missing or ordered after a conflicting rule. Request the nested URL directly with the network panel open.
Blank page below a subpath The base href does not match the deployment path. Inspect script, stylesheet, and lazy-chunk URLs in emitted HTML.
JavaScript has text/html MIME type A missing asset was rewritten to index.html. Exclude assets from the SPA catch-all and correct the requested filename or base path.
API works locally but fails in production Check the public API origin, HTTPS, CORS response headers, credentials mode, authentication callback URL, and proxy order.
Chunk load error after release Old HTML or a service worker points at removed chunks. Use atomic releases, revalidate HTML, retain old assets briefly, and test an already-open tab.
SSR process exits or never becomes healthy Verify the platform start command, PORT binding, runtime version, server dependencies, browser-only APIs, memory limit, and startup logs.
Hydration mismatch or layout jump Server and browser rendered different DOM. Remove nondeterministic template output and move browser-only initialization to browser render hooks.
  • Compare the failed request URL, status, response Content-Type, response body, and cache headers before changing code.
  • Reproduce against the preview deployment and the production origin, bypassing custom DNS or an extra CDN when possible.
  • Roll back when a critical journey is broken; investigate on the failed immutable artifact instead of repairing production manually.
Confirm the page outcome

Release Review

8 checks
  • I can identify whether the release is static CSR, SSR, or prerendered and deploy the correct artifacts.
  • I can build the intended configuration, inspect output and budgets, and avoid putting secrets in browser code.
  • I can configure base href and SPA fallback without turning missing static files into successful HTML responses.
  • I can verify deep links, lazy chunks, API access, caching, monitoring, and rollback after deployment.
  • I can match CSR, SSR, prerendered, or hybrid routes to their required artifacts and runtime.
  • I can apply different cache policies to route HTML, hashed assets, service-worker files, and public configuration.
  • I can configure and verify the build, output, fallback, preview, and rollback flow on a popular managed host.
  • I can package CSR with Nginx or deploy SSR to a runtime without confusing browser and server artifacts.

Release Review Questions

Publish the generated directory that directly contains index.html, not the workspace or dist root. Configure unknown application routes such as /orders to fall back to that index.html, while allowing real assets and backend endpoints to resolve normally. Set the base href to the actual deployment path; a GitHub project site usually needs /repository-name/ rather than /. Because outputPath is configurable, inspect the generated files instead of assuming the directory name.

Cache hashed JavaScript, CSS, fonts, and images for a long time because their names change with each build. Keep index.html short-lived or revalidated so it points to the latest files.

No. CSR and outputMode static builds can use static hosting. Request-time RenderMode.Server routes require a supported Angular adapter or a server runtime that executes the generated server application.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.