Build your app

ng build compiles your app into a bundle, the single file a Lynx app runs from. This page covers what the build produces, production and development builds, size budgets and customizing the build tool.

To turn the bundle into apps you can install, see Run on iOS and Android.

Build the bundle

ng build

The build writes its output to dist/, or to the build target's outputPath if you set one:

dist/
├── main.lynx.bundle
├── main.web.bundle
└── static/
    ├── image/
    │   └── logo.bf916cea19.png
    └── font/
        └── Inter-Regular.275384a067.ttf
FileWhat it is
main.lynx.bundleYour whole app: compiled code, templates and styles. iOS and Android run this file
main.web.bundleThe same app for the web preview
static/Images, fonts, SVGs and media your code imports. Small files are put inside the bundle instead

A bundle is like the JavaScript and CSS of a web app packed into one file. It doesn't run on its own: a host app with the Lynx engine loads it. See How a Lynx app runs.

ng build runs the @blotch/angular-lynx-build:application builder. It bundles with RSpeedy, Lynx's build tool, and takes the entry point from the build target's browser option, as in any Angular app.

Production and development builds

ng build makes a production build: minified, with Angular's dev mode off, and AngularLynx's debugging and profiling code removed.

As in Angular, the optimization option decides which kind of build you get. There's no separate mode option:

  • ng build uses the build target's defaultConfiguration, which is production after ng add.
  • ng build -c development uses ng new's development configuration ("optimization": false), with dev mode on.
  • Flags override single options, e.g. ng build --source-map.
  • ng serve -c production serves a production build.

Some tools only work in development builds, such as LynxLogger and the render counters.

Rebuild on every change

ng build --watch

This rebuilds the bundle whenever a file changes, like the npm run watch script that ng new adds. It can't be combined with --platform. While developing, use ng serve instead.

Lazy code ships in the bundle

Lazy routes (loadComponent()) and @defer blocks work as written. Their code is built into main.lynx.bundle, though, not into separate files.

So lazy loading doesn't make the bundle smaller. It still delays creating the views until they're needed. See Routing and @defer.

Budgets

Budgets fail the build when it grows past a size you set. They work as in a web app, with the same units and messages: over the warning size the build prints a warning, and over the error size it fails.

angular.json
"configurations": {
  "production": {
    "budgets": [
      { "type": "initial", "maximumWarning": "2MB", "maximumError": "5MB" },
      { "type": "anyComponentStyle", "maximumWarning": "4kB", "maximumError": "8kB" }
    ]
  }
}
  • initial checks each entry's Lynx bundle. anyComponentStyle checks each component's stylesheet.
  • The web preview bundle isn't checked.
  • Why 2 MB? ng add raises ng new's initial budget from 500 kB and 1 MB to 2 MB and 5 MB. A Lynx bundle holds Angular twice, once for each of Lynx's two threads, so a new app's bundle is already about 1 MB.

The build plugin's README explains what every budget type measures.

Customize RSpeedy

An app doesn't need a lynx.config.ts. Add one to change something RSpeedy does, such as its environments, its entries or the AngularLynx plugin's options. Whatever it doesn't set still comes from angular.json.

Import defineConfig and the plugin from @blotch/angular-lynx-build, which brings RSpeedy with it:

lynx.config.ts
import { defineConfig, pluginAngularLynx } from '@blotch/angular-lynx-build';

export default defineConfig({
  plugins: [pluginAngularLynx({ enableCSSInheritance: true })],
});
  • The plugin's options are listed in the build API reference.
  • RSpeedy's own options, such as output.assetPrefix, are in RSpeedy's docs.
  • Another config file? Point the build target's config option at it.