The `roodDir` compiler option not being respected when using SWC
Is there an existing issue for this?
- [X] I have searched the existing issues
Current behavior
The rootDir compiler option in tsconfig.json is not being respected when building a NestJS project with SWC. When SWC is not used, the rootDir compiler option determines the directory structure in the output directory.
Minimum reproduction code
https://github.com/DaleSeo/nestjs-typescript-starter-edqvzv
Steps to reproduce
- clone the above repository
- run
npm i - run
nest buildand check the contents of the generated dist directory
- run
nest build -b swc --type-checkand check the contents of the generated dist directory
- notice that the directory structure is different (the
srcdirectory has disappeared).
Expected behavior
Both nest build and nest build -b swc --type-check should generate identical build outputs for consumers who wish to utilize the swc builder.
Package
- [X] I don't know. Or some 3rd-party package
- [ ]
@nestjs/common - [ ]
@nestjs/core - [ ]
@nestjs/microservices - [ ]
@nestjs/platform-express - [ ]
@nestjs/platform-fastify - [ ]
@nestjs/platform-socket.io - [ ]
@nestjs/platform-ws - [ ]
@nestjs/testing - [ ]
@nestjs/websockets - [ ] Other (see below)
Other package
No response
NestJS version
10.3.0
Packages versions
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@swc/cli": "^0.1.63",
"@swc/core": "^1.3.101",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"prettier": "^3.0.0",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3"
},
Node.js version
18.17.0
In which operating systems have you tested?
- [X] macOS
- [ ] Windows
- [ ] Linux
Other
No response
Same Issue. (Different dist structure when using SWC)
I want to point out that if you take Nest's default .swcrc
.swcrc
{
"module": {
"type": "commonjs"
},
"jsc": {
"target": "es2021",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true,
"useDefineForClassFields": false
},
"keepClassNames": true,
"baseUrl": "./"
},
"minify": false
}
And then run swc ./ -d dist-swc --source-root ./ to mimic the rootDir option (unless there's another swc option I missed) it still outputs directly to dist-swc, not dist-swc/src
Why do you have src dir in dist while compiling with tsc in the first place?
Do you have any ts files outside src you wish to compile?
Yup exactly, we have files outside src we wish to compile
We also have folders like scripts that contain some TypeScript code. To clarify, I believe this issue is to suggest making it configurable through tsconfig.json instead of enforcing a specific folder structure. This will make the transition to SWC easier for most projects.
any progress?
Having the same issue with @nestjs/[email protected]. I'm finding that pnpm swc . -d dist works fine (as well as tsc):
dist/
src/
main.js
scripts/
some-script.js
src/
main.ts
scripts/
some-script.ts
but nest build with SWC builder doesn't:
dist/
main.js
some-script.js
src/
main.ts
scripts/
some-script.ts
My src/ and script/ output are mixed up!
My .swcrc:
{
"$schema": "https://json.schemastore.org/swcrc",
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": true,
"decorators": true,
"dynamicImport": true
},
"baseUrl": ".",
"target": "es2021",
"loose": false,
"externalHelpers": false,
"transform": {
"react": {
"runtime": "automatic",
"importSource": "@emotion/react"
}
}
},
"module": {
"type": "commonjs",
"strict": true,
"strictMode": true,
"lazy": true,
"noInterop": false
},
"sourceMaps": true,
"exclude": ["node_modules", "dist"]
}
my nest-cli.json
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": ".",
"entryFile": "src/index",
"compilerOptions": {
"deleteOutDir": true,
"tsConfigPath": "tsconfig.build.json",
"manualRestart": true,
"builder": {
"type": "swc"
}
}
}
my tsconfig.json:
{
"compilerOptions": {
"allowJs": false,
"module": "commonjs",
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"isolatedModules": false,
"allowSyntheticDefaultImports": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2021",
"esModuleInterop": true,
"sourceMap": true,
"jsx": "react",
"resolveJsonModule": true,
"strictNullChecks": true,
"skipLibCheck": true,
"outDir": "./dist",
"rootDir": ".",
"incremental": true
},
"include": [
"src/*.ts",
"src/**/*.ts",
"scripts/*.ts",
],
"exclude": ["node_modules", "dist"]
}
@williamdclt
I encountered the same issue, and it was caused by the --strip-leading-paths option being enabled by default. https://swc.rs/docs/usage/cli#–strip-leading-paths
The problem was fixed by changing it as follows:
nest-cli.json
"builder": {
"type": "swc",
"options": {
"stripLeadingPaths": false
}
},
Feel free to let me know if you need any further assistance!
Additional Information:
The following needs to be added:
"builder": {
"type": "swc",
"options": {
"stripLeadingPaths": false,
"includeDotfiles": true
}
}
With this change, it will work correctly even in watch mode.