nx icon indicating copy to clipboard operation
nx copied to clipboard

Nuxt application missing type declaration and path alias when setting up a new Nx workspace with @nx/nuxt

Open vorapongsan opened this issue 1 year ago • 11 comments

Current Behavior

When creating a new monorepo with a Nuxt application, the tsconfig of the app does not extend from the base tsconfig.json that is automatically generated from nuxt. This issue results in missing type declaration for Nuxt. Consequently, after adding a Nuxt module, the application is unable to import composables from #imports, #components, other Nuxt-specific composables or components or path alias

<script setup lang="ts">
//Cannot find module '#components' or its corresponding type declarations.ts(2307)
import { NxWelcome } from '#components';
//Cannot find module '#imports' or its corresponding type declarations.ts(2307)
import { useState } from '#imports';
//Cannot find module '@/composabels' or its corresponding type declarations.ts(2307)
import { useApi } from '@/composabels';

//Property 'client' does not exist on type 'ImportMeta'.ts(2339)
if(import.meta.client){

}
</script>

There appears to be a misconfiguration with the tsConfig setting in the nuxt.config.ts file. The current setting results in the creation of a tsconfig.json file at an incorrect location. This misplacement leads to a missing ./tsconfig.app.json within the Nuxt application's buildDir

//./apps/nuxtapp/nuxt.config.ts
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { defineNuxtConfig } from 'nuxt/config';

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  workspaceDir: '../../',
  srcDir: 'src',
  buildDir: '../../dist/apps/nuxtapp/.nuxt',
  devtools: { enabled: true },
  devServer: {
    host: 'localhost',
    port: 4200,
  },
  typescript: {
    typeCheck: true,
    tsConfig: {
      extends: './tsconfig.app.json',
    },
  },
  imports: {
    autoImport: false,
  },

  css: ['~/assets/css/styles.scss'],

  vite: {
    plugins: [nxViteTsPaths()],
  },
  nitro: {
    output: {
      dir: '../../dist/apps/nuxtapp/.output',
    },
  },
});

In the tsconfig.json file that is automatically generated by the Nuxt application, the extends property fails to locate the tsconfig.app.json file, which should be in the ./apps/nuxtapp directory. Additionally, the base tsconfig's paths setting is not included in this automatically generated tsconfig.json. It seems necessary to integrate the monorepo's tsconfig paths into the nuxt.config.ts to ensure that the paths are automatically generated correctly.

//./dist/apps/nuxtapp/.nuxt/tsconfig.json
// Generated by nuxi
{
  "compilerOptions": {
    "forceConsistentCasingInFileNames": true,
    "jsx": "preserve",
    "jsxImportSource": "vue",
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "skipLibCheck": true,
    "isolatedModules": true,
    "useDefineForClassFields": true,
    "strict": true,
    "noImplicitThis": true,
    "esModuleInterop": true,
    "types": [],
    "verbatimModuleSyntax": true,
    "allowJs": true,
    "noEmit": true,
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    "paths": {
      "~": [
        "../../../../apps/nuxtapp/src"
      ],
      "~/*": [
        "../../../../apps/nuxtapp/src/*"
      ],
      "@": [
        "../../../../apps/nuxtapp/src"
      ],
      "@/*": [
        "../../../../apps/nuxtapp/src/*"
      ],
      "~~": [
        "../../../../apps/nuxtapp"
      ],
      "~~/*": [
        "../../../../apps/nuxtapp/*"
      ],
      "@@": [
        "../../../../apps/nuxtapp"
      ],
      "@@/*": [
        "../../../../apps/nuxtapp/*"
      ],
      "assets": [
        "../../../../apps/nuxtapp/src/assets"
      ],
      "assets/*": [
        "../../../../apps/nuxtapp/src/assets/*"
      ],
      "public": [
        "../../../../apps/nuxtapp/src/public"
      ],
      "public/*": [
        "../../../../apps/nuxtapp/src/public/*"
      ],
      "#app": [
        "../../../../node_modules/nuxt/dist/app"
      ],
      "#app/*": [
        "../../../../node_modules/nuxt/dist/app/*"
      ],
      "vue-demi": [
        "../../../../node_modules/nuxt/dist/app/compat/vue-demi"
      ],
      "#vue-router": [
        "./vue-router-stub"
      ],
      "#imports": [
        "./imports"
      ],
      "#build": [
        "."
      ],
      "#build/*": [
        "./*"
      ],
      "#components": [
        "./components"
      ]
    }
  },
  "include": [
    "./nuxt.d.ts",
    "../../../../apps/nuxtapp/**/*",
    "../../../../apps/nuxtapp/src/**/*",
    "../../../../node_modules/@nuxt/devtools/runtime",
    "../../../../node_modules/@nuxt/telemetry/runtime",
    "../../../../apps/nuxtapp",
    "../../../../node_modules/nuxt/dist/app",
    "../../../../node_modules/nuxt/dist/app/compat/vue-demi",
    "./vue-router-stub",
    "./imports",
    "."
  ],
  "exclude": [
    "../../../../apps/nuxtapp/node_modules",
    "../../../../node_modules",
    "../../../../node_modules/nuxt/node_modules",
    "../../../../node_modules/@nuxt/devtools/runtime/server",
    "../../../../node_modules/@nuxt/telemetry/runtime/server",
    "../../../../apps/nuxtapp/dist",
    "../.output"
  ],
  "extends": "./tsconfig.app.json"
}

Expected Behavior

When creating a Nuxt application, it should automatically integrate Nuxt-specific type declarations to enable full IntelliSense support within the IDE. This facilitates auto-suggestions while typing code, provided that the type declarations. And merge Monorepo tsconfig's paths into tsconfig that Nuxt automatically generates.

GitHub Repo

No response

Steps to Reproduce

Setting up a new Nx workspace with @nx/nuxt

npx create-nx-workspace@latest --preset=nuxt

Nx Report

>  NX   Report complete - copy this into the issue template

   Node   : 20.11.0
   OS     : win32-x64
   yarn   : 3.3.0

   nx                 : 18.0.4
   @nx/js             : 18.0.4
   @nx/linter         : 18.0.4
   @nx/eslint         : 18.0.4
   @nx/workspace      : 18.0.4
   @nx/cypress        : 18.0.4
   @nx/devkit         : 18.0.4
   @nx/eslint-plugin  : 18.0.4
   @nrwl/tao          : 18.0.4
   @nx/vite           : 18.0.4
   @nx/vue            : 18.0.4
   @nx/web            : 18.0.4
   typescript         : 5.3.3
   ---------------------------------------
   Community plugins:
   @nx/nuxt : 18.0.4

Failure Logs

No response

Package Manager Version

No response

Operating System

  • [ ] macOS
  • [ ] Linux
  • [X] Windows
  • [ ] Other (Please specify)

Additional Information

No response

vorapongsan avatar Feb 18 '24 05:02 vorapongsan

Here is what I changed to remove the import errors:

nuxt.config.ts

  typescript: {
    typeCheck: true,
    // I removed this tsConfig extend
    // tsConfig: {
    //   extends: './tsconfig.app.json',
    // },
  },

tsconfig.json

{
  "compilerOptions": {},
  "files": [],
  "include": [],
  "references": [
    // I removed this reference
    // {
    //   "path": "./tsconfig.app.json"
    // }
  ],
 // I changed this extend to point to the .nuxt folder
  "extends": "../../dist/apps/my-app/.nuxt/tsconfig.json"
}

This solution works for me but is probably not ideal since I don't think it would be possible to use libraries from the /libs folder. This is what I will use until the @nx/nuxt plugin is fixed.

jpleclerc avatar Feb 21 '24 15:02 jpleclerc

I solved like this.

  1. remove tsconfig.app.json

  2. change buildDir path to ./.nuxt

    // nuxt.config.ts
    export default defineNuxtConfig({
     buildDir: './.nuxt',
    });
    
  3. change the tsconfig options in nuxt.config.ts

    // nuxt.config.ts
    import { fileURLToPath } from 'url';
    
    export default defineNuxtConfig({
    typescript: {
     typeCheck: true,
     tsConfig: {
        compilerOptions: {
         baseUrl: '.',
       },
     extends: fileURLToPath(
       new URL('../../tsconfig.base.json', import.meta.url),
        ),
      },
    },
    });
    

    I think tsconfig.base.json overwrites the baseUrl in the default setting which is provided by @nx/nuxt. It might be the reason why alias doesn' work.

  4. change your tsconfig.json which located in your nuxt project. In your case, it would be nuxtapp/tsconfig.

    {
      "compilerOptions": {},
      "references": [
        {
          "path": "./tsconfig.spec.json"
        }
      ],
      "extends": "./.nuxt/tsconfig.json"
    }
    

I wish this can help you.

c-jeongyyun avatar Feb 23 '24 05:02 c-jeongyyun

This is weird. I created a reproduction in a minimale setup so someone from the core team could take a look.

If you open the my-app/NxWelcome.vue File. There are no types for useTest. https://github.com/JulianMar/nuxt-types

I can take a look after the weekend, but there definitly need to be some changes to the way typescript is setup now. Anyways, the NX Team did some great work already on this plugin!

JulianMar avatar Feb 23 '24 16:02 JulianMar

@mandarini do you have an idea how we can solve this? As with the approaches mentioned above we cannot use libraries we create in nx. I think nuxt using the compilerOptions.paths property overwrites the paths from the base typescript file. I don't know of a way to combine these two paths properties as every search for merging two tsconfigs leads to alot of issues about it but no final result. I could kinda solve it by using an alias in nuxt. Its in the newest commit on my reproduction

Maybe you can help! Thank you :)

JulianMar avatar Mar 01 '24 09:03 JulianMar

We will look into it @JulianMar ! Can you try out our latest canary version and let me know if it works for you? We added the Nuxt types in the includes array. Or I think the fix could already be in the latest version of Nx. Please try it out and let me know? You would have to generate a new Nuxt project and see how the new tsconfig.json is set up.

mandarini avatar Mar 01 '24 09:03 mandarini

Still not working. I added a repro here https://github.com/JulianMar/nuxt-types-2

VSCode is telling me there is no tsConfig file for the NxWelcome Component.

JulianMar avatar Mar 01 '24 09:03 JulianMar

I've seen this in Nx's documentation for create Nuxt app in previous versions. Nuxt will import Nx's paths into compilerOptions.paths section of its tsconfig.json. But I think it only solves problem about paths in Nuxt's tsconfig.json. And then, I change tsconfig.json in apps project to ../../dist/apps/nuxt-app/.nuxt/tsconfig.json. I think it's just a temporary solution, and I'm not sure about, How to combine tsconfig from Nx's base and Nuxt automatically generated. (When I change tsconfig.json in folder app to Nuxt's tsconfig in buildDir, VSCode can show type of nuxt. this method for change tsconfig extends is similar to @jpleclerc and @c-jeongyyun )

import { defineNuxtConfig } from 'nuxt/config';
import { join } from 'path';
import { workspaceRoot } from '@nx/devkit';

/**
 * read the compilerOptions.paths option from a tsconfig and return as aliases for Nuxt
 **/
function getMonorepoTsConfigPaths(tsConfigPath: string) {
  const tsPaths = require(tsConfigPath)?.compilerOptions?.paths as Record<
    string,
    string[]
  >;

  const alias: Record<string, string> = {};
  if (tsPaths) {
    for (const p in tsPaths) {
      // '@org/something/*': ['libs/something/src/*'] => '@org/something': '{pathToWorkspaceRoot}/libs/something/src'
      alias[p.replace(/\/\*$/, '')] = join(
        workspaceRoot,
        tsPaths[p][0].replace(/\/\*$/, '')
      );
    }
  }

  return alias;
}

export default defineNuxtConfig({
  alias: getMonorepoTsConfigPaths('../../tsconfig.base.json'),
}

vorapongsan avatar Mar 02 '24 05:03 vorapongsan

image

I'm fork from @JulianMar and test with function getMonorepoTsConfigPaths. When use with alias in nuxt config without extends from tsconfig.base.json, VSCode known Nuxt Type, But when I use its with extends from tsconfig.base.json, paths alias not working

import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { defineNuxtConfig } from 'nuxt/config';
import { join } from 'path';
import { workspaceRoot } from '@nx/devkit';
import { fileURLToPath } from 'url';

/**
 * read the compilerOptions.paths option from a tsconfig and return as aliases for Nuxt
 **/
function getMonorepoTsConfigPaths(tsConfigPath: string) {
  const tsPaths = require(tsConfigPath)?.compilerOptions?.paths as Record<
    string,
    string[]
  >;

  const alias: Record<string, string> = {};
  if (tsPaths) {
    for (const p in tsPaths) {
      // '@org/something/*': ['libs/something/src/*'] => '@org/something': '{pathToWorkspaceRoot}/libs/something/src'
      alias[p.replace(/\/\*$/, '')] = join(
        workspaceRoot,
        tsPaths[p][0].replace(/\/\*$/, '')
      );
    }
  }

  return alias;
}

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  workspaceDir: '../',
  srcDir: 'src',
  devtools: { enabled: true },
  alias: getMonorepoTsConfigPaths('../tsconfig.base.json'),
  devServer: {
    host: 'localhost',
    port: 4200,
  },
  typescript: {
    typeCheck: true,
    tsConfig: {
      extends: fileURLToPath(new URL('../tsconfig.base.json', import.meta.url)),
    },
  },
  imports: {
    autoImport: false,
  },

  css: ['~/assets/css/styles.css'],

  vite: {
    plugins: [nxViteTsPaths()],
  },
});

image

vorapongsan avatar Mar 02 '24 05:03 vorapongsan

Hey, this issue seems a bit stale but it's still relevant and nx/nuxt is not usable for our team right now. Maybe to get some progress we could ask the Nuxt team for some help?

JulianMar avatar Apr 03 '24 06:04 JulianMar

Hello @mandarini, it seems you are the core developer for this module. Thanks for the great work, it's very nice to have a native nuxt integration.

This issue is still a big blocker for our Team of Developers. With the current Setup, there is no possibility to have types for your libraries and for the nuxt auto imports. You have to decide between the two options. @vorapongsan has provided a basic way to fix it. In my reproduction mentioned above the issue is easy to replicate.

I would help code a fix, but I am not sure how to handle it. Do you or maybe @danielroe have an idea how to best handle this issue with typescript, nx and nuxt?

Thanks for you answers! It's greatly appreciated

JulianMar avatar Apr 18 '24 08:04 JulianMar

Yeah, this tsconfig.json hell is kinda of annoying when working with nx+nuxt. I tried everything to be able to use nx libs and nuxt apps, but each suggestion I try, breaks a different think/layer =/

rafapaulin avatar May 03 '24 20:05 rafapaulin

Thank you for bringing this issue to our attention! I want to assure you that I will take a look as soon as I can. Your patience and understanding in this matter is greatly appreciated.

Coly010 avatar May 10 '24 15:05 Coly010

Thank you for bringing this issue to our attention! I want to assure you that I will take a look as soon as I can. Your patience and understanding in this matter is greatly appreciated.

Sure, no problem @Coly010, let me know if I can help in any way :)

rafapaulin avatar May 10 '24 16:05 rafapaulin

Hi all,

Unfortunately, this issue arises due to a current limitation with Nx's approach to tsconfig paths and how Nuxt handles aliases (which get mapped to tsconfig paths) within Integrated Monorepos.

One workaround is to copy the compilerOptions.paths from .nuxt/tsconfig.json into either your project's tsconfig.json or the workspace's tsconfig.base.json.

Copying it into your project's tsconfig.json would require also copying any compilerOptions.paths defined in the workspace tsconfig.base.json. Consequently, any new paths added to tsconfig.base.json would need to be manually added to your project's tsconfig.json thereafter. Alternatively, copying it to your tsconfig.base.json would necessitate updating all paths to be relevant to a single project, potentially impacting multiple other projects. Another option is to use a Package Based Monorepo approach with NPM/Yarn/PNPM workspaces. More details can be found here: Nx - Integrated vs Package Based.

We apologize for any inconvenience caused by this limitation. Given the current constraints, there is no immediate resolution available from our side.

Thank you for your understanding.

Coly010 avatar Jun 05 '24 16:06 Coly010

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

github-actions[bot] avatar Jul 06 '24 00:07 github-actions[bot]