Search code examples
typescriptvisual-studio-codenext.jsnode-modules

@node_modules keeps showing in Visual Studio Code auto import and suggesions in Nextjs 15


When I try to import a component or function from a dependency vscode displays @node_modules before the path, for example if I tried to import toast from sonner vscode is gonna import it like this:

import { toast } from "@node_modules/sonner/dist"

instead of:

import { toast } from "sonner"

here is my tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@*": ["./*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

This happens with all dependencies not only sonner

I made sure typescript.preferences.importModuleSpecifier is set to "shortest" but I still have the same problem

I only started experiencing this issue when I started using nextjs 15, it didn't happen in nextjs 14 or any other framework or language.


Solution

  • Turns out that ignoring recommendations is a bad idea. In the create-next-app if your tried to use @* in the import alias, it's gonna tell you that it's not recommended. Despite that, I'm used to bypassing that in the tsconfig.json and VSCode never had an issue. However, since NextJS 15, VSCode started having that issue.

    Anyway the fix is to leave the default as it is:

        "paths": {
          "@/*": ["./*"]
        }
    

    Here is the full fixed tsconfig.json:

    {
      "compilerOptions": {
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve",
        "incremental": true,
        "plugins": [
          {
            "name": "next"
          }
        ],
        "paths": {
          "@/*": ["./*"]
        }
      },
      "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
      "exclude": ["node_modules"]
    }