Skip to content

⚡ perf(build): migrate compilation from tsc/babel to SWC#210

Open
cteyton wants to merge 3 commits intomainfrom
swc-migration
Open

⚡ perf(build): migrate compilation from tsc/babel to SWC#210
cteyton wants to merge 3 commits intomainfrom
swc-migration

Conversation

@cteyton
Copy link
Contributor

@cteyton cteyton commented Mar 13, 2026

Explanation

Migrate the monorepo's TypeScript compilation pipeline from tsc/babel to SWC, and optimize the MCP server Docker startup by removing redundant dependency pre-builds.

Type of Change

  • Improvement/Enhancement
  • Refactoring

Affected Components

  • Domain packages affected: All packages under packages/ and tools/packmind-plugin
  • Frontend / Backend / Both: Both
  • Breaking changes (if any): None — SWC is a drop-in replacement for tsc/babel compilation

What Changed

1. SWC migration (b4b055c5)

  • Replaced tsc and babel compilation with @swc/cli / @swc/core across all packages
  • Added .swcrc configuration files to each package with appropriate settings (decorators, dynamic imports, CommonJS output)
  • Updated every project.json to use @nx/js:swc executor instead of @nx/js:tsc
  • Removed @babel/core, @babel/preset-env, babel-plugin-transform-vite-meta-env and .babelrc from packages/ui
  • Updated packages/ui/jest.config.ts to use @swc/jest transformer
  • Updated apps/api/webpack.config.js to use swc-loader instead of ts-loader
  • Cleaned up package.json devDependencies accordingly

2. MCP server Docker startup optimization (516dba76)

  • Overrode the global @nx/esbuild:esbuild dependsOn with an empty array in apps/mcp-server/project.json
  • esbuild now bundles directly from source via tsconfig paths, skipping 14 sequential SWC package builds that were redundant

Testing

  • Unit tests added/updated
  • Manual testing completed
  • Test coverage maintained or improved

Test Details:

  • Updated packages/ui/jest.config.ts to use @swc/jest as transformer
  • Verified all existing tests pass with the new SWC compilation
  • Verified MCP server Docker startup works without pre-building dependencies

TODO List

  • CHANGELOG Updated

Reviewer Notes

  • Each package gets its own .swcrc file to handle package-specific settings (e.g., decorator metadata, dynamic imports)
  • The nx.json global targetDefaults for @nx/js:swc replaces the previous @nx/js:tsc defaults
  • The MCP server optimization is safe because esbuild already resolves source files via tsconfig paths — the intermediate SWC build artifacts were never actually used

🤖 Generated with Claude Code

cteyton and others added 2 commits March 13, 2026 17:09
- Upgrade @swc/core ~1.5.7 → ~1.15.18, @swc/cli, @swc/helpers, @swc-node/register
- Migrate 21 packages from @nx/js:tsc to @nx/js:swc with per-package .swcrc
- Replace ts-loader with swc-loader in apps/api webpack config
- Replace babel-jest with @swc/jest for packages/ui tests
- Remove unused tslib from all package dependencies
- Remove babel-jest and packages/ui/.babelrc
- Set babel: false in nx.json generators

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e-builds

Override the global @nx/esbuild:esbuild dependsOn with an empty array
so esbuild bundles directly from source via tsconfig paths, skipping
14 sequential SWC package builds that were redundant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 13, 2026

Greptile Summary

This PR replaces the monorepo's TypeScript compilation pipeline from tsc/babel to SWC across all 18+ packages and tools, and removes a redundant 14-package pre-build chain from the MCP server's Docker startup.

Key changes:

  • Every project.json migrated from @nx/js:tsc to @nx/js:swc, each backed by a new per-package .swcrc config
  • apps/api/webpack.config.js switches from ts-loader to swc-loader with correct NestJS-compatible options (legacyDecorator, decoratorMetadata, useDefineForClassFields: false); ForkTsCheckerWebpackPlugin is correctly retained for type-safety
  • Packages using NestJS decorators (packages/coding-agent, packages/editions) have appropriate .swcrc with full decorator support; the remaining packages correctly omit it
  • packages/ui/jest.config.ts migrated from babel-jest to @swc/jest with inline TSX/React config; all babel devDependencies cleaned up from the root package.json
  • apps/mcp-server/project.json sets dependsOn: [] — safe because tsconfig.base.json paths resolve to TypeScript source files and esbuild's bundle: true already traverses the source graph directly
  • Minor: target: 'es2021' in the webpack inline config is inconsistent with 'es2022' used in all .swcrc files; and sourceMaps: true is unconditional in swc-loader even though devtool is false in production

Confidence Score: 4/5

  • This PR is safe to merge. The SWC migration is comprehensive and correct; no functional regressions found.
  • The migration is well-structured: decorator-using packages have correct SWC configs, webpack path aliases still resolve to source, babel is fully removed, and the MCP server optimization is sound given tsconfig paths point to source files. Score is 4 rather than 5 due to two minor style inconsistencies in the webpack config (es2021 vs es2022 target, and unconditional sourceMaps in production) that don't cause breakage but could cause confusion.
  • apps/api/webpack.config.js has a minor target version mismatch (es2021 vs es2022) and unconditional sourceMaps in production — both worth tidying up.

Important Files Changed

Filename Overview
apps/api/webpack.config.js Migrates from ts-loader to swc-loader with correct NestJS decorator settings (legacyDecorator, decoratorMetadata, useDefineForClassFields: false). ForkTsCheckerWebpackPlugin is properly retained. Minor: target is es2021 while all .swcrc files use es2022, and sourceMaps: true generates maps that are discarded in production (devtool: false).
apps/mcp-server/project.json Removes dependsOn: ["^build"] to skip 14 sequential package builds. Safe because tsconfig.base.json paths all point to source files and esbuild bundles with bundle: true directly from source.
nx.json Replaces @nx/js:tsc targetDefaults with @nx/js:swc and disables babel for new @nx/react application generators. Clean global configuration update.
packages/ui/jest.config.ts Correctly replaces babel-jest with @swc/jest. TSX parsing enabled, React automatic runtime configured, CommonJS module output set — all correct for a React component library under Jest.
packages/coding-agent/.swcrc Correctly enables decorators: true, legacyDecorator: true, and decoratorMetadata: true — required for the NestJS-decorated source files in this package.
packages/editions/.swcrc Correctly enables full decorator support (legacyDecorator + decoratorMetadata) matching the NestJS controllers/services/modules in this package.
packages/accounts/.swcrc Standard SWC config with decorators: false — correct since the accounts package does not use TypeORM or NestJS class decorators directly.
package.json Cleanly removes all babel devDependencies (@babel/core, @babel/preset-env, @babel/preset-react, @babel/preset-typescript, babel-jest) and upgrades @swc/* packages. Correctly adds swc-loader for webpack.
packages/linter-ast/.swcrc Standard SWC config added to the one package that was already using @nx/js:swc executor (project.json unchanged). Decorators: false is correct for this package.
packages/ui/.babelrc Correctly deleted. No remaining babel consumers found in the codebase; packages/ui tests now use @swc/jest directly.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph Before["Before - tsc and babel"]
        S1[TypeScript Source] -->|ts-loader| W1[Webpack Bundle API]
        S2[Package Sources] -->|nx:tsc executor| D1[dist/packages]
        S3[packages/ui tests] -->|babel-jest| J1[Jest Output]
        D1 -->|dependsOn build| M1[MCP Server Build]
    end

    subgraph After["After - SWC"]
        S4[TypeScript Source] -->|swc-loader| W2[Webpack Bundle API]
        S4 -->|ForkTsCheckerPlugin| TC[Type Check]
        S5[Package Sources] -->|nx:swc executor + .swcrc| D2[dist/packages]
        S6[packages/ui tests] -->|swc-jest| J2[Jest Output]
        S7[MCP Server Source] -->|esbuild bundle=true| M2[MCP Server Build]
        TP[tsconfig paths to src] -.->|resolves source directly| M2
    end

    style Before fill:#fff3cd
    style After fill:#d4edda
Loading

Comments Outside Diff (2)

  1. apps/api/webpack.config.js, line 67 (link)

    Target version inconsistent with package .swcrc files

    The target here is 'es2021', but every package-level .swcrc file (e.g. packages/coding-agent/.swcrc, packages/editions/.swcrc, and all 18 others) uses 'es2022'. Since the API runs on Node.js 22, which fully supports ES2022, both values are harmless at runtime — but the inconsistency can be confusing when comparing compilation settings across the monorepo.

  2. apps/api/webpack.config.js, line 71 (link)

    Source maps generated but discarded in production

    sourceMaps: true is unconditional, so SWC appends inline source-map comments to every compiled module even in production builds. However, devtool is already set to false in production, which tells webpack to drop all source maps from the final bundle. The SWC-emitted maps are therefore generated and then immediately discarded, adding a small overhead to every production build.

    Consider aligning this with the devtool setting:

Last reviewed commit: 3da761f

Delete packages/ui/.babelrc (no consumers after SWC migration) and
remove @babel/core, @babel/preset-env, @babel/preset-react,
@babel/preset-typescript from root devDependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant