diff --git a/packages/vite/package.json b/packages/vite/package.json index 4a4eb6a9324dfd..59a2e6e432f2ec 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -34,7 +34,8 @@ "dotenv": "~10.0.0", "enquirer": "~2.3.6", "@nx/devkit": "file:../devkit", - "@nx/js": "file:../js" + "@nx/js": "file:../js", + "tsconfig-paths": "^4.1.2" }, "peerDependencies": { "vite": "^4.3.4", @@ -53,6 +54,7 @@ "./executors": "./executors.js", "./src/executors/*/schema.json": "./src/executors/*/schema.json", "./src/executors/*.impl": "./src/executors/*.impl.js", - "./src/executors/*/compat": "./src/executors/*/compat.js" + "./src/executors/*/compat": "./src/executors/*/compat.js", + "./plugins/nx-tsconfig-paths.plugin": "./plugins/nx-tsconfig-paths.plugin.js" } } diff --git a/packages/vite/plugins/nx-tsconfig-paths.plugin.ts b/packages/vite/plugins/nx-tsconfig-paths.plugin.ts new file mode 100644 index 00000000000000..159c58bb790243 --- /dev/null +++ b/packages/vite/plugins/nx-tsconfig-paths.plugin.ts @@ -0,0 +1,60 @@ +import { stripIndents, workspaceRoot } from '@nx/devkit'; +import { existsSync } from 'node:fs'; +import { relative, join, resolve, posix } from 'node:path'; +import { loadConfig, createMatchPath, MatchPath } from 'tsconfig-paths'; + +// TODO(caleb): should we provide a way to override anything for the plugin? + +export function nxViteTsPaths() { + let matchTsPath: MatchPath; + + return { + name: 'nx-vite-ts-paths', + configResolved(config: any) { + const projectRoot = config.root; + // TODO(caleb): verify on windows to see what type of paths vite returns posix vs win32 + const projectRootFromWorkspaceRoot = relative(workspaceRoot, projectRoot); + + const foundTsConfigPath = getTsConfig(projectRootFromWorkspaceRoot); + if (!foundTsConfigPath) { + throw new Error(stripIndents`Unable to find a tsconfig in the workspace! +There should at least be a tsconfig.base.json or tsconfig.json in the root of the workspace ${workspaceRoot}`); + } + const parsed = loadConfig(foundTsConfigPath); + + if (parsed.resultType === 'failed') { + throw new Error(`Failed loading tsonfig at ${foundTsConfigPath}`); + } + + matchTsPath = createMatchPath(parsed.absoluteBaseUrl, parsed.paths, [ + ['exports', '.', 'import'], + ]); + }, + resolveId(source: string) { + const resolvedFile = matchTsPath(source); + + if (!resolvedFile) { + console.warn( + `[Nx Vite TsPaths] Unable to resolve ${source} with tsconfig paths` + ); + } + + return resolvedFile; + }, + }; +} + +function getTsConfig( + projectRoot: string, + tmpTsConfigName = 'tsconfig.generated.json' +): string { + return [ + resolve(join(workspaceRoot, 'tmp', projectRoot, tmpTsConfigName)), + resolve(join(workspaceRoot, 'tsconfig.base.json')), + resolve(join(workspaceRoot, 'tsconfig.json')), + ].find((tsPath) => { + if (existsSync(tsPath)) { + return tsPath; + } + }); +} diff --git a/packages/vite/src/executors/build/build.impl.ts b/packages/vite/src/executors/build/build.impl.ts index 015177879c8dda..8f3313c46c91a0 100644 --- a/packages/vite/src/executors/build/build.impl.ts +++ b/packages/vite/src/executors/build/build.impl.ts @@ -25,6 +25,7 @@ export async function* viteBuildExecutor( const projectRoot = context.projectsConfigurations.projects[context.projectName].root; + // TODO(caleb): do we need to register the paths anymore or just make tsconfig? registerPaths(projectRoot, options, context); const normalizedOptions = normalizeOptions(options); diff --git a/packages/vite/src/executors/dev-server/dev-server.impl.ts b/packages/vite/src/executors/dev-server/dev-server.impl.ts index f43342fa396627..7507400e57a240 100644 --- a/packages/vite/src/executors/dev-server/dev-server.impl.ts +++ b/packages/vite/src/executors/dev-server/dev-server.impl.ts @@ -20,6 +20,7 @@ export async function* viteDevServerExecutor( const projectRoot = context.projectsConfigurations.projects[context.projectName].root; + // TODO(caleb): do we need to register the paths anymore or just make tsconfig? registerPaths(projectRoot, options, context); // Retrieve the option for the configured buildTarget. diff --git a/packages/vite/src/utils/executor-utils.ts b/packages/vite/src/utils/executor-utils.ts index 470f1ff73d8038..11308e1e2f0d45 100644 --- a/packages/vite/src/utils/executor-utils.ts +++ b/packages/vite/src/utils/executor-utils.ts @@ -35,7 +35,9 @@ export function registerPaths( const tsConfig = resolve(projectRoot, 'tsconfig.json'); options.buildLibsFromSource ??= true; - if (!options.buildLibsFromSource) { + if (options.buildLibsFromSource) { + registerTsConfigPaths(tsConfig); + } else { const { dependencies } = calculateProjectDependencies( context.projectGraph, context.root, @@ -49,9 +51,6 @@ export function registerPaths( projectRoot, dependencies ); - registerTsConfigPaths(tmpTsConfig); - } else { - registerTsConfigPaths(tsConfig); } } diff --git a/packages/vite/src/utils/generator-utils.ts b/packages/vite/src/utils/generator-utils.ts index 7c5ee1deec5703..4430ec762888d8 100644 --- a/packages/vite/src/utils/generator-utils.ts +++ b/packages/vite/src/utils/generator-utils.ts @@ -583,13 +583,14 @@ export function createOrEditViteConfig( host: 'localhost', },`; + // viteTsConfigPaths({ + // root: '${offsetFromRoot(projectConfig.root)}', + // }), const pluginOption = ` plugins: [ ${dtsPlugin} ${reactPlugin} - viteTsConfigPaths({ - root: '${offsetFromRoot(projectConfig.root)}', - }), + nxViteTsPaths(), ], `; @@ -628,7 +629,7 @@ export function createOrEditViteConfig( /// import { defineConfig } from 'vite'; ${reactPluginImportLine} - import viteTsConfigPaths from 'vite-tsconfig-paths'; + import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; ${dtsImportLine} export default defineConfig({