Skip to content

angular-rspack: Non-JS/TS assets piped to Babel parser instead of Rspack loaders #32690

@miluoshi

Description

@miluoshi

Current Behavior

Building an Angular app with @nx/angular-rspack (either through the plugin or via the Rspack executor) fails when the app imports JSON (or any non-JS/TS) modules. Angular’s JavaScript transformer treats the JSON as JavaScript and forwards it to Babel parser, which then fails with a parse error:

SyntaxError: .../data/timezones.json: Missing semicolon.
  at .../@angular/build/node_modules/@babel/core/lib/parser/index.js
  at .../@angular/build/node_modules/@babel/core/lib/transformation/normalize-file.js

The same project builds successfully when using the Webpack executor (@nx/angular:webpack-browser).

Expected Behavior

Non-JS/TS assets such as .json should be handled by Rspack’s native JSON module support and should not be pre-processed by Angular’s Babel step.

GitHub Repo

No response

Steps to Reproduce

  1. Create a new workspace and generate Angular app with Rspack as bundler:
npx create-nx-workspace myorg
npx nx g @nx/angular:app myapp --bundler=rspack
  1. In apps/myapp/tsconfig.app.json, ensure "resolveJsonModule": true.

  2. Create a JSON file with an object at the top level, for example apps/myapp/src/app/data/timezones.json:

{  "UTC": "+00:00" }
  1. Import it from a TypeScript file, for example apps/<app>/src/app/app.component.ts:
import timezones from './data/timezones.json';

console.log(timezones.UTC);
  1. Build the app with Rspack:
npx nx build myapp
  1. Observe a Babel parse error like:
SyntaxError: .../data/timezones.json: Missing semicolon.

Nx Report

Node           : 22.16.0
OS             : darwin-arm64
Native Target  : aarch64-macos
yarn           : 1.22.19

nx (global)            : 21.3.11
nx                     : 21.4.1
@nx/js                 : 21.4.1
@nx/jest               : 21.4.1
@nx/eslint             : 21.4.1
@nx/workspace          : 21.4.1
@nx/angular            : 21.4.1
@nx/cypress            : 21.4.1
@nx/devkit             : 21.4.1
@nx/eslint-plugin      : 21.4.1
@nx/module-federation  : 21.4.1
@nx/plugin             : 21.4.1
@nx/react              : 21.4.1
@nx/rollup             : 21.4.1
@nx/rspack             : 21.4.1
@nx/storybook          : 21.4.1
@nx/vite               : 21.4.1
@nx/web                : 21.4.1
@nx/webpack            : 21.4.1
typescript             : 5.8.3

---------------------------------------
Community plugins:
@ngrx/component-store    : 20.0.1
@ngrx/effects            : 20.0.1
@ngrx/entity             : 20.0.1
@ngrx/operators          : 20.0.1
@ngrx/schematics         : 20.0.1
@ngrx/store              : 20.0.1
@nx/s3-cache             : 2.1.0
@testing-library/angular : 16.0.0
ng2-charts               : 4.1.1
---------------------------------------

Operating System

  • macOS
  • Linux
  • Windows
  • Other (Please specify)

Additional Information

Nx’s Rspack integration runs Angular compilation and then invokes Angular’s JavaScriptTransformer.transformData on every emitted file, including non-JS assets like JSON. This causes JSON to be forwarded to Babel parser and parsed as JavaScript, which fails for object-top-level JSON.

Relevant code: packages/angular-rspack-compiler/src/compilation/build-and-analyze.ts

for (const { 
  filename, 
  contents 
} of await angularCompilation.emitAffectedFiles()) {
  const normalizedFilename = normalize(filename.replace(/^[A-Z]:/, ''));
  // This line unconditionally passes any asset to `@angular/build` which uses Babel parser to parse it
  await javascriptTransformer
    .transformData(normalizedFilename, contents, true, false)
    .then((contents) => {
      typescriptFileCache.set(
        normalizedFilename, 
        Buffer.from(contents).toString()
      );
    });
}

The impact is that JSON imports (both static and dynamic) fail, and potentially any non-JS/TS asset referenced from TypeScript (e.g., CSS, SVG-as-source) could be incorrectly handed to Babel.

A fix in @nx/angular-rspack-compiler would be to skip non-JS/TS files before calling transformData, letting Rspack process them via its module rules. For example:

const JS_LIKE = /\.[cm]?[jt]sx?$/;
for (const { filename, contents } of await angularCompilation.emitAffectedFiles()) {
  const normalizedFilename = normalize(filename.replace(/^[A-Z]:/, ''));
  if (!JS_LIKE.test(normalizedFilename)) {
    const text = typeof contents === 'string' ? contents : Buffer.from(contents).toString();
    typescriptFileCache.set(normalizedFilename, text);
    continue;
  }
  const out = await javascriptTransformer.transformData(normalizedFilename, contents, true, false);
  typescriptFileCache.set(normalizedFilename, Buffer.from(out).toString());
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions