Importing Zone.js/node And Using Modern Sass Compiler Throws An Error With Vite/AnalogJS

by ADMIN 89 views

Introduction

When working with Angular applications, especially those that utilize modern features like server-side rendering (SSR) and Angular Material, developers often encounter issues with the sass compiler. In this article, we will delve into a specific problem that arises when using the modern sass compiler with Vite and AnalogJS, and how to resolve it.

The Issue

The issue at hand is related to the use of zone.js in conjunction with the modern sass compiler. When using SSR and Angular Material, the sass compiler throws an error. This error is caused by zone.js patching the Promise which is being used inside the sass-embedded package used for sass compilation.

Steps to Reproduce

To reproduce this issue, follow these steps:

  1. Clone the repo
  2. Run npm install.
  3. Run npx vite or npx ng serve.
  4. Visit the local development URL.
  5. Note the error shown above.

Workarounds

There are two workarounds to resolve this issue:

1. Use Zoneless change detection and not load zone.js/node in the main.server.ts file.

By using zoneless change detection, you can avoid the issue altogether. This can be achieved by not loading zone.js/node in the main.server.ts file.

2. Configure Vite to use the legacy sass compiler

Alternatively, you can configure Vite to use the legacy sass compiler. This can be done by setting the api option to 'legacy' in the scss preprocessor options.

/// <reference types="vitest" />

import { defineConfig } from 'vite';
import analog from '@analogjs/platform';

// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
  build: {
    target: ['es2020'],
  },
  css: {
    preprocessorOptions: {
      scss: {
        api: 'legacy' // fixes the error, but displays deprecation warnings
      }
    }
  },
  resolve: {
    mainFields: ['module'],
  },
  plugins: [
    analog(),
  ],
}));

Minimal Reproduction

A minimal reproduction of this bug can be found in the following GitHub repository:

https://github.com/brandonroberts/analog-angular-material-zonejs

Environment

This issue was discovered in the following environment:

Angular CLI: 19.2.10
Node: 22.14.0
Package Manager: npm 10.9.2
OS: darwin arm64

Angular: 19.2.9
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1902.10
@angular-devkit/build-angular   19.2.10
@angular-devkit/core            19.2.10
@angular-devkit/schematics      19.2.10
@angular/build                  19.2.10
@angular/cdk                   19.2.14
@angular/cli                    19.2.10
@angular/material               19.2.14
@schematics/angular             19.2.10
rxjs                            7.8.2
typescript                      5.8.3
zone.js                         0.15.0

Conclusion

Q: What is the issue with using zone.js/node and modern sass compiler with Vite/AnalogJS?

A: The issue arises when zone.js patches the Promise which is being used inside the sass-embedded package used for sass compilation. This causes an error when using SSR and Angular Material.

Q: What are the steps to reproduce this issue?

A: To reproduce this issue, follow these steps:

  1. Clone the repo
  2. Run npm install.
  3. Run npx vite or npx ng serve.
  4. Visit the local development URL.
  5. Note the error shown above.

Q: What are the workarounds to resolve this issue?

A: There are two workarounds to resolve this issue:

1. Use Zoneless change detection and not load zone.js/node in the main.server.ts file.

By using zoneless change detection, you can avoid the issue altogether. This can be achieved by not loading zone.js/node in the main.server.ts file.

2. Configure Vite to use the legacy sass compiler

Alternatively, you can configure Vite to use the legacy sass compiler. This can be done by setting the api option to 'legacy' in the scss preprocessor options.

/// <reference types="vitest" />

import { defineConfig } from 'vite';
import analog from '@analogjs/platform';

// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
  build: {
    target: ['es2020'],
  },
  css: {
    preprocessorOptions: {
      scss: {
        api: 'legacy' // fixes the error, but displays deprecation warnings
      }
    }
  },
  resolve: {
    mainFields: ['module'],
  },
  plugins: [
    analog(),
  ],
}));

Q: What is the minimal reproduction of this bug?

A: A minimal reproduction of this bug can be found in the following GitHub repository:

https://github.com/brandonroberts/analog-angular-material-zonejs

Q: What is the environment in which this issue was discovered?

A: This issue was discovered in the following environment:

Angular CLI: 19.2.10
Node: 22.14.0
Package Manager: npm 10.9.2
OS: darwin arm64

Angular: 19.2.9
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1902.10
@angular-devkit/build-angular   19.2.10
@angular-devkit/core            19.2.10
@angular-devkit/schematics      19.2.10
@angular/build                  19.2.10
@angular/cdk                   19.2.14
@angular/cli                    19.2.10
@angular/material               .2.14
@schematics/angular             19.2.10
rxjs                            7.8.2
typescript                      5.8.3
zone.js                         0.15.0

Q: Is there anything else I should know about this issue?

A: Yes, using Analog 1.16.0 is also related to this issue.