From 13b65dfe191ca18a577421019c9a9e285d5c95a3 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Tue, 15 Oct 2024 12:20:43 -0400 Subject: [PATCH] fix(@angular/build): allow direct bundling of TSX files with application builder When using the application builder with `isolatedModules`, the bundler will directly handle TypeScript transpilation and bundling. Previously, any input TSX files were loaded by the bundler as TS files. This difference caused errors when attempting to process the files since the syntax differs between TSX and TS. The appropriate loader will now be used if the input file is TSX in this situation. --- .../typescript-isolated-modules_spec.ts | 28 +++++++++++++++++++ .../tools/esbuild/angular/compiler-plugin.ts | 15 +++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/packages/angular/build/src/builders/application/tests/behavior/typescript-isolated-modules_spec.ts b/packages/angular/build/src/builders/application/tests/behavior/typescript-isolated-modules_spec.ts index 738e454adb01..06e66cbd6da9 100644 --- a/packages/angular/build/src/builders/application/tests/behavior/typescript-isolated-modules_spec.ts +++ b/packages/angular/build/src/builders/application/tests/behavior/typescript-isolated-modules_spec.ts @@ -47,5 +47,33 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => { expect(result?.success).toBe(true); }); + + it('supports TSX files with isolated modules enabled and enabled optimizations', async () => { + // Enable tsconfig isolatedModules option in tsconfig + await harness.modifyFile('tsconfig.json', (content) => { + const tsconfig = JSON.parse(content); + tsconfig.compilerOptions.isolatedModules = true; + tsconfig.compilerOptions.jsx = 'react-jsx'; + + return JSON.stringify(tsconfig); + }); + + await harness.writeFile('src/types.d.ts', `declare module 'react/jsx-runtime' { jsx: any }`); + await harness.writeFile('src/abc.tsx', `export function hello() { return

Hello

; }`); + await harness.modifyFile( + 'src/main.ts', + (content) => content + `import { hello } from './abc'; console.log(hello());`, + ); + + harness.useTarget('build', { + ...BASE_OPTIONS, + optimization: true, + externalDependencies: ['react'], + }); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBe(true); + }); }); }); diff --git a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts index 16c4b01fd459..f4ff8a5de1d9 100644 --- a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts +++ b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts @@ -8,6 +8,7 @@ import type { BuildFailure, + Loader, Metafile, OnStartResult, OutputFile, @@ -461,9 +462,21 @@ export function createCompilerPlugin( typeScriptFileCache.set(request, contents); } + let loader: Loader; + if (useTypeScriptTranspilation || isJS) { + // TypeScript has transpiled to JS or is already JS + loader = 'js'; + } else if (request.at(-1) === 'x') { + // TSX and TS have different syntax rules. Only set if input is a TSX file. + loader = 'tsx'; + } else { + // Otherwise, directly bundle TS + loader = 'ts'; + } + return { contents, - loader: useTypeScriptTranspilation || isJS ? 'js' : 'ts', + loader, }; });