Cory Rylan

My name is , Google Developer Expert, Speaker, Software Developer. Building Design Systems and Web Components.

Follow @coryrylan
Angular

Using Angular CLI and Wireit

Cory Rylan

- 5 minutes

This article has been updated to the latest version Angular 17 and tested with Angular 16. The content is likely still applicable for all Angular 2 + versions.

As Angular and front-end projects grow in complexity, build and test times inevitably increase, impacting developer productivity and CI/CD pipeline efficiency. Long build times can slow down development cycles, delay deployments, and increase infrastructure costs. Wireit, a open source build orchestration tool, offers a solution by introducing intelligent caching and task orchestration to your npm scripts.

In this post, we'll explore how to integrate Wireit with the Angular CLI to significantly improve build and test performance through caching, while maintaining the familiar Angular development experience.

Angular CLI

The Angular CLI is the standard tool for creating, building, and testing Angular applications. Starting with Angular v20, creating a new project is as simple as running ng new followed by your project name. The CLI provides a comprehensive set of commands that handle everything from development servers to production builds.

At its core, the Angular CLI provides two essential commands for any Angular project:

  • ng build - Compiles your Angular application into static files ready for deployment
  • ng test - Runs your unit tests using Karma and Jasmine

A typical Angular project's package.json includes these standard scripts:

"scripts": {
  "ng": "ng",
  "start": "ng serve",
  "build": "ng build",
  "watch": "ng build --watch --configuration development",
  "test": "ng test"
}

While these commands work well for small to medium projects, as your codebase grows, you'll notice build times increasing from seconds to minutes. This is where Wireit comes in to help optimize your workflow.

Wireit

Wireit is a build orchestration tool that adds intelligent caching and task dependencies to npm scripts. Instead of running the same build or test commands repeatedly, Wireit caches the results and only re-runs them when the input files have changed. This can dramatically reduce build times, especially in CI/CD environments where builds run frequently.

To get started with Wireit, first install it as a dev dependency:

npm install --save-dev wireit

Then, you can convert your existing npm scripts to use Wireit. Here's how to transform the basic Angular build script:

"scripts": {
  "build": "wireit"
  ...
},
"wireit": {
  "build": {
    "command": "ng build",
    "files": [
      "src/**/*",
      "!src/**/*.spec.ts",
      "angular.json",
      "package.json",
      "tsconfig.json",
      "tsconfig.app.json"
    ],
    "output": [
      "dist/angular-wireit/**/*"
    ]
  }
}

The Wireit configuration has two critical properties:

  • files: Specifies which files Wireit should monitor for changes. When any of these files change, Wireit knows it needs to re-run the build. Notice we exclude test files (!src/**/*.spec.ts) since they don't affect the build output.
  • output: Defines the build artifacts that Wireit should cache. If the input files haven't changed, Wireit can skip the build entirely and restore these cached outputs.

Let's see the caching in action. When you run the build for the first time:

✅ Ran 1 script and skipped 0 in 2.2s.

Wireit executes the Angular build normally. But when you run the same command again without changing any source files:

✅ Ran 0 scripts and skipped 1 in 0s.

The build completes instantly! Wireit detected that no input files changed, so it skipped the build entirely. This is particularly powerful in CI environments where multiple jobs might need the same build artifacts.

Configuring Tests with Wireit

Tests require a slightly different configuration since they don't produce deployable artifacts but still benefit from caching:

"scripts": {
  ...
  "test": "wireit"
},
"wireit": {
  ...
  "test": {
    "command": "ng test --no-watch --no-progress --browsers=ChromeHeadless",
    "files": [
      "src/**/*",
      "angular.json",
      "package.json",
      "tsconfig.json",
      "tsconfig.app.json",
      "tsconfig.spec.json"
    ],
    "output": [
      "dist/test-out/**/*"
    ]
  }
}

Note that the test configuration:

  • Includes all source files (both application and test files) in the files array
  • Uses a different output directory (dist/test-out) than the build, typically for artifacts like test coverage reports.
  • Runs tests in headless mode for consistent CI execution

This separation ensures that build and test caches don't interfere with each other, allowing you to cache both independently.

Wireit Service

So far, we've configured Wireit for one-time build and test commands. But what about long-running processes like development servers or watch modes? Wireit handles these with a special service configuration.

A Wireit service is a long-running process that doesn't produce cacheable output but may depend on other tasks. Services are perfect for development workflows where you want the benefits of Wireit's dependency management without caching.

"scripts": {
  "start": "wireit",
  "test:watch": "wireit"
},
"wireit": {
  "start": {
    "command": "ng serve",
    "dependencies": [
      "build"
    ],
    "service": true
  },
  "test:watch": {
    "command": "ng test",
    "service": true
  }
}

The service: true flag tells Wireit that these commands:

  • Run continuously until manually stopped
  • Don't produce cacheable output
  • Should be restarted if their dependencies change

Notice that the start script depends on build. This means Wireit will ensure a fresh build exists before starting the development server, useful when switching branches or pulling changes.

Wireit Dependencies

One of Wireit's most powerful features is its dependency management system. You can define relationships between scripts, and Wireit will automatically execute them in the correct order, running independent tasks in parallel for optimal performance.

The dependencies array allows any script to specify which other scripts must complete successfully before it runs. For example, you might want to ensure your code builds successfully before running tests, or that linting passes before building.

Wireit analyzes the entire dependency tree and executes tasks as efficiently as possible. If two tasks don't depend on each other, they'll run in parallel. This automatic parallelization can significantly speed up complex workflows.

Creating a CI Entry Point

A common pattern is to create a single entry point for CI pipelines that runs all necessary checks:

"scripts": {
  "ci": "wireit",
  "build": "wireit",
  "test": "wireit",
  ...
},
"wireit": {
  "ci": {
    "dependencies": [
      "build",
      "test"
    ]
  },
  "build": {
    "command": "ng build",
    "files": ["src/**/*", "!src/**/*.spec.ts", "angular.json", "package.json", "tsconfig.json", "tsconfig.app.json"],
    "output": ["dist/angular-wireit/**/*"]
  },
  "test": {
    "command": "ng test --no-watch --no-progress --browsers=ChromeHeadless",
    "files": ["src/**/*", "angular.json", "package.json", "tsconfig.json", "tsconfig.app.json", "tsconfig.spec.json"],
    "output": ["dist/test-out/**/*"]
  }
}

Now your CI pipeline can simply run npm run ci, and Wireit will:

  1. Check if the build cache is valid
  2. Check if the test cache is valid
  3. Run both in parallel if they're independent, or in sequence if one depends on the other
  4. Skip any tasks where the cache is still valid

This approach scales very well to monorepos where you might have dozens of interdependent projects. Wireit ensures everything runs in the correct order while maximizing parallelization and caching.

Conclusion

Wireit levels up the Angular CLI development experience by adding intelligent caching and dependency management without changing your familiar workflow. By wrapping your existing npm scripts with Wireit, you can achieve:

  • Dramatic speed improvements: Skip redundant builds and tests when files haven't changed
  • Better CI/CD efficiency: Reduce pipeline times
  • Simplified orchestration: Define dependencies between tasks and let Wireit handle the execution order
  • Monorepo readiness: Scale your build system as your project grows

You can also adopt Wireit incrementally. Start with your slowest scripts and expand from there. Your team can continue using the same npm commands they're familiar with while benefiting from Wireit's optimizations under the hood.

To see a complete example of Angular CLI with Wireit integration, check out the demo below!

View Demo Code on Github   
Bluesky Facebook LinkedIn Email
 

No spam. Short occasional updates on Web Development articles, videos, and new courses in your inbox.

Related Posts

Angular

Creating Dynamic Tables in Angular

Learn how to easily create HTML tables in Angular from dynamic data sources.

Read Article
Web Components

Reusable Component Patterns - Default Slots

Learn about how to use default slots in Web Components for a more flexible API design.

Read Article
Web Components

Reusable Component Anti-Patterns - Semantic Obfuscation

Learn about UI Component API design and one of the common anti-patterns, Semantic Obfuscation.

Read Article