Build & Release

Angular workspace

angular.json defines two projects:

metronic

The application. Targets: build, serve, extract-i18n, test, lint.

metronic-e2e

Protractor end-to-end scaffolding. Targets: e2e, lint.

metronic is the name of the admin template the project started from. It is the Angular project name only; it has no runtime meaning.

Build configurations: production, development, swtest, test2.

npm scripts

npm run pre-build

Generate environment.ts only.

npm run pre-build:proxy

Generate environment.ts and proxy.json.

npm start

Dev server with --proxy-config proxy.json.

npm run build

Development build.

npm run build:prod

pre-build then a production build.

npm run build:ci

Production build without pre-build (CI generates it separately).

npm run build:swtest

Build with the swtest configuration (service-worker testing).

npm run build:stats

Build with --stats-json.

npm run analyze

Production build plus webpack-bundle-analyzer.

npm run bundle-report

Analyzer against an existing dist/stats.json.

npm test

Karma in watch mode.

npm run test:ci

lint:quiet then headless Karma with coverage.

npm run test:pre-push

Headless Karma, no coverage (the pre-push hook).

npm run lint / lint:fix / lint:cache

ESLint variants.

npm run format-all

Prettier over src/app/*/.{ts,js}.

npm run extract-translations

ngx-translate-extract over ./src.

npm run cypress:open

Cypress runner.

Every Angular CLI script in package.json runs Node with --max_old_space_size=4096. The Angular 12 build runs out of heap without it. Do not drop the flag when editing a script, and add it to any new script that invokes the CLI.

CodeBuild pipeline

buildspec.yaml:

env:
    variables:
        PYB_IAC_AWS_DEFAULT_REGION: 'us-east-1'
    secrets-manager:
        NPM_TOKEN: aws-codebuild-token-eva

phases:
    install:
        runtime-versions: { nodejs: 12, python: 3.8 }
        commands:
            - export CHROME_BIN=/usr/bin/chromium-browser
            - echo "//npm.pkg.github.com/:_authToken=\${NPM_TOKEN}" >> ~/.npmrc
            - echo "@payability:registry=https://npm.pkg.github.com/" >> ~/.npmrc
            - npm install
            - npm install -g @angular/cli
    pre_build:
        commands:
            - npm run pre-build
            # - npm run test:ci                                   (1)
    build:
        commands:
            - |
                if [ $ENV_NAME = "prod" ] || [ $ENV_NAME = "staging" ] ; then
                  npm run build:prod
                else
                  npm run build
                fi
artifacts:
    files: ./**/*
    name: pyb-ng2-sd-build
    base-directory: dist
1 The test step is commented out. CI does not currently run the unit suite — the only automated gate is the Husky pre-push hook on a developer’s machine.

ENV_NAME

Selects the backend environment. prod and staging get a production build.

ENV_TYPE

Selects the domain and config profile.

NPM_TOKEN

Pulled from Secrets Manager to authenticate against GitHub Packages.

CHROME_BIN

Set for Karma, even though the test step is disabled.

Artifact

The contents of dist/, named pyb-ng2-sd-build.

build:prod runs pre-build again, so the environment file is generated twice for production builds. Harmless, but it means buildTime reflects the second run.

Version stamping

config/pre-build.js writes three provenance fields into environment.ts:

version

From package.json.

buildTime

new Date().toString() at generation time.

env

The ENV_NAME value.

They are surfaced in the UI footer, so a screenshot identifies the exact build.

Bumping the app version means editing package.json and adding a CHANGELOG.md entry.

Service worker

Registered only in production:

ServiceWorkerModule.register('ngsw-worker.js', {
    enabled: environment.production,
    registrationStrategy: 'registerImmediately',
})

ngsw-config.json asset groups:

Group Install mode Resources

app

prefetch

index.html, manifest.webmanifest, .css, .js, pyb-glyph-dark.svg

assets

lazy

/assets/** and image/font extensions

blog-media

lazy, updateMode: lazy

https://www.payability.com/wp-content/uploads/*/.*

Plus data groups for themes.

ServiceWorkerService watches for a new version and prompts a reload through the update-app-banner component.

Use npm run build:swtest to build with service-worker behaviour enabled outside production.

PWA

src/manifest.webmanifest declares the installable app. modals/pwa-ios-install-modal/ gives iOS users add-to-home-screen instructions, since iOS has no install prompt.

Bundle analysis

$ npm run analyze                # build + open the analyzer
$ npm run build:stats            # just produce dist/stats.json
$ npm run bundle-report          # analyze an existing stats.json

source-map-explorer is also available as a dependency.

Every feature module is lazy-loaded, so a large initial bundle usually means something eagerly imported a feature module — check AppModule and PartialsModule first.

Git hooks

Installed by the postinstall script (husky install).

pre-commit

pretty-quick --staged, then lint-staged per .lintstagedrc.json.

pre-push

npm run test:pre-push — headless Karma without coverage.

Since CI does not run tests, the pre-push hook is the only automated test gate. Bypassing it with --no-verify means untested code reaches the pipeline.

Browser support

browserslist at the repository root and src/browserslist drive transpilation targets and autoprefixing. polyfills.ts covers the remainder.