Setting up pure Angular 21 Workspace as a Monorepo

Jan. 28, 2026
Setting up pure Angular 21 Workspace as a Monorepo

This document outlines the steps required to setup a pure Angular CLI (that is, without nx or other higher level tools) monorepo project. These instructions are for Angular 21, the current version at the time of writing this. The document is divided into two halves -- the first half covers setting up the workspace for multiple projects which are a mix of applications and libraries. The second half lists the steps required to configure vitest, the default test framework that Angular now uses.

Workspace configuration

  1. Install @angular/cli globally.

  2. Create an empty Angular workspace.

     $ ng new  --no-create-application
     

    This will create the folder <workspace_name>. All future commands are to be run from this folder. 3. 3.

  3. Generate the required app projects.

    $ ng g application  --project-root apps/.
    

    Our monorepo has a folder structure where all applications are stored in separate subfolders under the parent folder apps.

  4. Generate the required library projects.

     $ ng g library  --project-root libs/
     

  5. Update <workspaceRoot>/tsconfig.json adding the paths to the libraries created. This will allow you to refer to the libraries you generated using a friendly name rather its entire path. For example, if one of the libraries you generated was named shared, you can update tsconfig.json as:

     {
       compilerOptions: {
         "baseUrl": ".",
         "paths": {
           "shared": ["libs/shared/src/public-api.ts"]
         }
       }
     }
    

    If you generated other libraries, add them to the paths as above. This will allow you to import a component from the library as:

     import { SharedComponent } from 'shared';
     

Also note that we added baseUrl. This directs tsc to refer to the paths relative to the value of this setting (It would assume paths are absolute otherwise).

Vitest Configuration

Angular 21 uses the quicker vitest for running its unit tests. However it's not set up when the workspace is created perhaps because we created an empty workspace to begin with. You're expected to do this explicitly.

Vitest is setup primarily by creating two files in each project in the workspace -- vitest.config.ts & test-setup.ts. The latter filename is just a convention, you can give it any name you want as long as you refer to the correct file in vitest.config.ts.

Also, if you would like to run and debug specific tests from your IDE (such as VSCode), you need to install a few additional packages. Let's assume that that's the environment that we're aiming for here. Adding these packages and tweaking the configuration to use these, would not in anyway degrade ng test command line. So we might as well do this.

$ npm install @analogjs/platform @analogjs/vite-plugin-angular @analogjs/vitest-angular -D

AnalogJS has published a few packages that makes the process of configuring the Angular's TestBed testing workhorse for invocation from the ng command line and the IDE's testing plugin seamless. Once you install this do the following (You need to repeat this for every project in the workspace):

  1. Update angular.json such that the builder for test architect's point to @analogjs/vitest-angular:test rather than the angular native unit test builder.
     "test": {
        "builder": "@analogjs/vitest-angular:test",
      }

Now when you issue ng test, it will use the @analogjs package as the default builder. But for @analogjs/vitest-angular:test to work we need to go through a couple of more steps listed below.

  1. Create vitest.config.ts in each project's root folder. It's content should look like this:

      import { defineConfig } from 'vite';
      import angular from '@analogjs/vite-plugin-angular';

    export default defineConfig(({ mode }) => ({ plugins: [angular()], test: { globals: true, setupFiles: ['src/test-setup.ts'], environment: 'jsdom', include: ['src/*/.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], reporters: ['default'], }, }));

    Note how test-setup.ts is referred to in setupFiles. We'll create this file in the next step.

  2. Create the file test-setup.ts in project's src/ folder. It's content shou;d look like this:

    import '@analogjs/vitest-angular/setup-snapshots';
    import { setupTestBed } from '@analogjs/vitest-angular/setup-testbed';
    import '@angular/compiler';

    setupTestBed();

    setupTestBed() will call TestBed.initTestEnvironment(), which readies the TestBed for running the individual suite of tests.

  3. Create tsconfig.spec.json in the project's root folder.

    {
      "extends": "../../tsconfig.json",
      "compilerOptions": {
        "outDir": "../../out-tsc/spec",
        "types": ["vitest/globals"]
      },
      "files": ["src/test-setup.ts"],
      "include": ["src//*.d.ts", "src//*.spec.ts"]
    }
    

    Pay attention to the files key. It's value explicitly adds test-setup.ts to the list of files to be transpiled.

  4. If you're using VSCode, install the Vitest official plugin. This will allow you to run the tests from within the IDE by clicking on the green play button on the left margin.