Blog

Angular AOT vs JIT

Key Takeaways

  • AOT compiles Angular templates during the build; JIT compiles them at runtime.
  • AOT is the normal Angular CLI application-build default, not a production-only optimization you must enable manually.
  • Browser-JIT execution needs the Angular runtime compiler. Precompiled templates don't require it.
  • AOT supports build-time template diagnostics and removes browser-side template compilation, but it doesn't guarantee a particular bundle-size or startup improvement.

Angular AOT vs JIT is primarily a comparison of when Angular templates become executable JavaScript. Ahead-of-Time compilation happens during the build; Just-in-Time compilation happens at runtime in the browser. For deployed applications, use AOT unless you have a specific runtime-compilation requirement.

What Is JIT Compilation in Angular?

JIT defers Angular template compilation until the application runs. The runtime compiler turns templates and related component metadata into executable code in the browser. Downloading JavaScript assets is a separate step; JIT isn't the mechanism that fetches those assets.

A browser-JIT application needs the compiler provided by @angular/compiler. How it reaches the browser depends on your tooling and bootstrap setup: the current CLI application builder includes it when building in JIT mode, while a custom pipeline must arrange for it to be available.

JIT also doesn't mean you skip the application build. TypeScript still needs conversion to JavaScript, and your tooling can still bundle and optimize that JavaScript. Angular template compilation is the work being deferred.

What Is AOT Compilation in Angular?

AOT performs Angular template compilation during the build, before the application reaches the browser. The browser receives executable template code rather than having to compile those templates itself.

Keep that separate from the rest of the build pipeline. TypeScript compilation converts TypeScript to JavaScript; bundling assembles application dependencies; minification reduces code size; tree-shaking removes unused code. AOT isn't another name for all these optimizations. Angular exposes build-output optimizations separately through the workspace configuration.

Our guide to JavaScript build tools explains the broader pipeline. For this comparison, focus on which side of the network boundary performs template compilation.

AOT
Build:   templates + metadata -> compiled template code -> bundle
Browser: download -> execute -> render
         No runtime compiler needed for precompiled templates

JIT
Build:   application code + template metadata -> bundle
Browser: download + runtime compiler -> compile templates -> render

Angular AOT vs JIT: Practical Differences

Both modes ultimately produce executable template code. Their practical differences concern when compilation happens, which diagnostics you get before deployment, and whether a compiler is needed at runtime.

ConcernAOTJIT
Template compilationTemplates compile during the build.Templates compile at runtime.
Browser compilerPrecompiled templates don't need the runtime compiler.Browser-side template compilation requires the runtime compiler.
Template diagnosticsThe build can report template binding and type errors.Runtime compilation doesn't provide AOT's build-time template checking.
Typical roleNormal application development and deployment.Selected testing and runtime-compilation workflows.

The Benefits of AOT over JIT

Smaller Payloads Without the Runtime Compiler

An application whose templates are already compiled doesn't need to download the Angular template compiler to execute them. That can reduce shipped JavaScript compared with an otherwise equivalent browser-JIT application. It doesn't guarantee that every AOT output directory will be smaller than every JIT output directory.

Don't assume an AOT setting makes every compiler import disappear. Explicitly importing runtime-compilation functionality introduces a separate dependency that you should inspect in the output.

Less Browser Startup Work

AOT removes browser-side template compilation from startup. It doesn't remove JavaScript downloading, parsing, execution, application initialization, or rendering. Those remain distinct costs, and a bottleneck elsewhere can dominate the result.

Measure transfer size separately from main-thread work. A smaller download is useful, but it isn't proof of faster rendering or better interaction performance.

Template Errors Before Deployment

Angular's template checker can identify missing component properties and incompatible input bindings during compilation. With strictTemplates enabled, it also checks more precise types in template expressions and bindings. For example, a binding to user.nmae can fail the build when the declared property is name.

Check angularCompilerOptions.strictTemplates in the application's TypeScript configuration and any configuration it extends. AOT and template-checking strictness are related but separate settings; enabling AOT isn't a substitute for reviewing your type-checking configuration. See Angular's template type-checking guide.

This is a concrete development benefit: you can catch template mistakes before a user reaches the affected screen. Keep a production build in your continuous-integration checks rather than relying only on tests.

Angular CLI Defaults and How to Check Your Build

The examples below target Angular 22 application workspaces using @angular/build:application. This builder uses esbuild, and its aot option defaults to true. Older or custom builders can have different constraints, so inspect your workspace before copying commands.

Run these commands from the workspace root, using your project's CLI. Replace my-app with the name under projects in angular.json:

ng version
ng config projects.my-app.architect.build
ng config projects.my-app.architect.serve

# Normal production build; AOT applies unless overridden.
ng build my-app --configuration production

ng version reports version information, and ng config reads stored workspace configuration. It doesn't print a fully resolved configuration containing every builder default.

To determine the effective compilation mode, check the following:

  1. The builder: confirm which builder the application's build target uses.
  2. Base options: inspect projects.my-app.architect.build.options.aot.
  3. Named configurations: inspect the selected configuration, such as build.configurations.production.aot, for an override.
  4. Command-line options: an explicit --aot value overrides the configured value.
  5. Local serving: check which build configuration the serve target selects through buildTarget.

Named configurations override base options; command-line options can override configuration values. If aot is absent everywhere, the application builder's default is true. Development configuration doesn't automatically mean JIT: ng serve can use AOT too.

For deployment details beyond compilation mode, see deploying applications with the Angular CLI.

How to Enable or Disable AOT

For this application builder, use --aot=true to request AOT explicitly or --aot=false to select JIT. For a persistent setting, configure aot in the build target's options or a named configuration. The build-command reference documents the option.

Compare Production Output Instead of Guessing

For a browser-only application using the builder above, build the same production configuration twice, changing only the compilation mode and output location:

ng build my-app --configuration production --aot=true \
  --output-path dist/compare-aot --stats-json

ng build my-app --configuration production --aot=false \
  --output-path dist/compare-jit --stats-json

--output-path selects the output location, and --stats-json generates bundle-analysis data. If your builder or application configuration rejects JIT, don't silently change unrelated settings to force a comparison; record that limitation instead.

  1. Check correctness first. Load both outputs and exercise the same routes. A build that fails at startup isn't a performance result.
  2. Inspect browser bundles. Compare initial JavaScript, lazy-loaded chunks, and the presence of compiler code. Don't count source maps or server artifacts as browser downloads.
  3. Use equivalent hosting. Keep compression, caching, application data, routes, browser, device, and throttling settings consistent.
  4. Record startup work. Compare transferred bytes and performance traces, separating script execution from rendering work.
  5. Repeat measurements. Compare several cold-load runs, then examine warm-cache behavior separately.

The Chrome DevTools Performance panel helps you inspect loading and main-thread activity. Treat the comparison as evidence about your application, not a universal AOT percentage improvement.

When Is JIT Still Useful?

  • Testing: some TestBed operations can use JIT capabilities even when application code is AOT-compiled. Test compilation and deployed application compilation aren't necessarily identical.
  • Specialized development pipelines: a custom workflow may choose JIT. Measure initial builds and incremental rebuilds in that workflow rather than assuming JIT is faster or makes deployment faster.
  • Runtime-generated templates: systems that compile genuinely new Angular templates after deployment need runtime-compilation capabilities. This is a specialized requirement with substantial security implications, not a reason to disable AOT for ordinary applications.

Dynamic components don't automatically require JIT. You can select and render an already compiled component using NgComponentOutlet or ViewContainerRef.createComponent; see Angular's programmatic component-rendering guide.

Common Mistakes

  • Comparing development JIT with production AOT. That mixes compilation mode with other optimization settings.
  • Assuming AOT means server-side rendering. AOT describes template compilation timing, not where pages are rendered.
  • Disabling AOT to hide template errors. Fix the binding, component import, or type declaration instead of moving the problem toward runtime.
  • Assuming AOT guarantees compiler-free output. Inspect runtime-compilation dependencies rather than relying on the flag alone.

Default to AOT for development and deployment. Keep JIT as an explicit exception with a documented requirement, a tested bootstrap path, and a security review.

FAQ

Is AOT enabled by default in Angular CLI production builds?

Yes. New Angular CLI applications use AOT by default, and the application builder defaults aot to true. Check angular.json and command-line overrides because a customized workspace can select JIT.

Does AOT always outperform JIT?

No. AOT removes browser-side template compilation and can avoid the runtime compiler download, but bundle size and startup gains depend on your application and build. Measure equivalent production builds rather than assuming a fixed improvement.

What does Angular AOT compile?

AOT compiles Angular templates and related component metadata into executable JavaScript during the build. TypeScript compilation, bundling, minification, and tree-shaking are separate concerns in the build pipeline.

When is JIT still useful in Angular?

JIT remains useful for some testing operations, specialized development pipelines, and systems that genuinely compile new templates at runtime. Dynamically displaying an already compiled component does not itself require JIT.

How can I check or switch between AOT and JIT?

Inspect your build target, selected configuration, and aot overrides in angular.json. For the application builder shown here, use ng build my-app --configuration production --aot=true for AOT or change the flag to --aot=false for JIT; browser-JIT execution requires the runtime compiler.

Further Reading

Written by Sam Erickson

Software engineer. I write every article on StackChief myself. Author of Mastering the Tech Interview. More about me