nx
nx copied to clipboard
Nuxt application missing type declaration and path alias when setting up a new Nx workspace with @nx/nuxt
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
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.
I solved like this.
-
remove
tsconfig.app.json
-
change buildDir path to
./.nuxt
// nuxt.config.ts export default defineNuxtConfig({ buildDir: './.nuxt', });
-
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. -
change your
tsconfig.json
which located in your nuxt project. In your case, it would benuxtapp/tsconfig
.{ "compilerOptions": {}, "references": [ { "path": "./tsconfig.spec.json" } ], "extends": "./.nuxt/tsconfig.json" }
I wish this can help you.
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!
@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 :)
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.
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.
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'),
}
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()],
},
});
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?
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
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 =/
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.
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 :)
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.
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.