nest icon indicating copy to clipboard operation
nest copied to clipboard

Path aliases / relative imports in a monorepo breaks `nest start`

Open ChazUK opened this issue 1 year ago • 1 comments
trafficstars

Is there an existing issue for this?

  • [X] I have searched the existing issues

Current behavior

When adding an external import to a Nest.js app inside a monorepo, an error occurs when running nest start:dev.

I have setup a repo using pnpm workspaces so that I can share code between different projects. To achieve clean imports I have used path aliases for the shared project, but the same happens when the import uses a relative path. https://github.com/ChazUK/nest-monorepo-import-error/blob/main/nest-project/src/app.controller.ts#L4

Normally running the start or build command creates a dist structure like below:

nest-project/
└─ dist/
   ├─ src/
   │  └─ main.js
   └─ src/
      ├─ main.js
      └─ app.controller.ts

But when adding this import it returns a different structure:

nest-project/
└─ dist/
   ├─ nest-project/
   │  └─ src/
   │     └─ main.js
   ├─ shared-project/
   │  └─ src/
   |     └─ index.js
   └─ src/
      ├─ main.js
      └─ app.controller.ts

Which then produces this error

Error: Cannot find module '/Users/.../pnpm-monorepo/nest-project/dist/main'
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1144:15)
    at Function.Module._load (node:internal/modules/cjs/loader:985:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
    at node:internal/main/run_main_module:28:49

tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2021",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "strictBindCallApply": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "paths": {
      "@shared": ["../shared-project/"]
    }
  }
}

Minimum reproduction code

https://github.com/ChazUK/nest-monorepo-import-error

Steps to reproduce

  1. pnpm i 2 pnpm run --filter nest-project start:dev

Expected behavior

Relative imports and path alisases should not break the Nest.js start command

Package

  • [ ] I don't know. Or some 3rd-party package
  • [X] @nestjs/common
  • [X] @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.0.0

Packages versions

{
  "name": "nest-project",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@nestjs/common": "^10.0.0",
    "@nestjs/core": "^10.0.0",
    "@nestjs/platform-express": "^10.0.0",
    "reflect-metadata": "^0.2.0",
    "rxjs": "^7.8.1"
  },
  "devDependencies": {
    "@nestjs/cli": "^10.0.0",
    "@nestjs/schematics": "^10.0.0",
    "@nestjs/testing": "^10.0.0",
    "@types/express": "^4.17.17",
    "@types/jest": "^29.5.2",
    "@types/node": "^20.3.1",
    "@types/supertest": "^6.0.0",
    "@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"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

Node.js version

20.11.1

In which operating systems have you tested?

  • [X] macOS
  • [ ] Windows
  • [ ] Linux

Other

Install pnpm https://pnpm.io/installation

ChazUK avatar May 10 '24 13:05 ChazUK

I'm getting the same issue. My main seems to have moved from dist/main to dist/src/main recently? I don't know what I did.

Here's my setup:

  • nestjs 10.3.2
  • node.js v20.12.1 / npm 10.5.0
  • macOS Sonoma 14.4.1 (23E224)

I can't reproduce it in my other macOS:


$ nest new my-project

$ cd my-project

$ npm i

$ npm run build

$ npm start start:prod

main is <projectDir>/dist/main

but in my existing project in my original macOS, main is <projectDir>/dist/src/main

Here's my tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2021",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false
  }
}

Edit: Problem solved. The culprit was <projectDir>/jest.config.ts causing <projectDir>dist/src/main .

i.e. my jest config file was in typescript.

It went back to <projectDir>dist/main as soon as I migrated back to <projectDir>/jest.config.js

I switched my jest config back to javascript and all is well.

NhxKR9uxTpAf6 avatar May 11 '24 04:05 NhxKR9uxTpAf6

@NhxKR9uxTpAf6 unfortunately that doesn't solve my problem as my dist folder is still being compiled into multiple sub-directories.

ChazUK avatar May 13 '24 09:05 ChazUK

Thank you for taking the time to submit your report! From the looks of it, this could be better discussed on our Discord. If you haven't already, please join here and send a new post in the #⁠ 🐈 nestjs-help forum. Make sure to include a link to this issue, so you don't need to write it all again. We have a large community of helpful members, who will assist you in getting this to work.

kamilmysliwiec avatar May 14 '24 06:05 kamilmysliwiec