diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 7ba40a15d5ff12..38c764b8092b23 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -36,8 +36,10 @@ "@nx/eslint": "file:../eslint", "@nx/vue": "file:../vue" }, + "peerDependencies": { + "vite": "^5.0.0" + }, "publishConfig": { "access": "public" - }, - "peerDependencies": {} + } } diff --git a/packages/nuxt/src/plugins/__snapshots__/plugin.spec.ts.snap b/packages/nuxt/src/plugins/__snapshots__/plugin.spec.ts.snap index 6a4bbc5d0fa46a..696ca792bd0efc 100644 --- a/packages/nuxt/src/plugins/__snapshots__/plugin.spec.ts.snap +++ b/packages/nuxt/src/plugins/__snapshots__/plugin.spec.ts.snap @@ -13,7 +13,7 @@ exports[`@nx/nuxt/plugin not root project should create nodes 1`] = ` "^build-something", ], "inputs": [ - "default", + "production", "^production", { "externalDependencies": [ @@ -25,7 +25,7 @@ exports[`@nx/nuxt/plugin not root project should create nodes 1`] = ` "cwd": "my-app", }, "outputs": [ - "{options.outputPath}", + "{workspaceRoot}/dist/my-app/", ], }, "my-serve": { @@ -50,8 +50,7 @@ exports[`@nx/nuxt/plugin not root project should create nodes 1`] = ` "cwd": "my-app", }, "outputs": [ - "{options.reportsDirectory}", - "{workspaceRoot}/coverage/my-app", + "{workspaceRoot}/coverage/{projectRoot}", ], }, }, @@ -73,7 +72,7 @@ exports[`@nx/nuxt/plugin root project should create nodes 1`] = ` "^build", ], "inputs": [ - "default", + "production", "^production", { "externalDependencies": [ @@ -85,7 +84,7 @@ exports[`@nx/nuxt/plugin root project should create nodes 1`] = ` "cwd": ".", }, "outputs": [ - "{options.outputPath}", + "dist/my-app/", ], }, "serve": { @@ -110,8 +109,7 @@ exports[`@nx/nuxt/plugin root project should create nodes 1`] = ` "cwd": ".", }, "outputs": [ - "{options.reportsDirectory}", - "{projectRoot}/coverage", + "{workspaceRoot}/coverage/{projectRoot}", ], }, }, diff --git a/packages/nuxt/src/plugins/plugin.spec.ts b/packages/nuxt/src/plugins/plugin.spec.ts index a7774aff08044b..f6190cddafb67d 100644 --- a/packages/nuxt/src/plugins/plugin.spec.ts +++ b/packages/nuxt/src/plugins/plugin.spec.ts @@ -2,29 +2,35 @@ import { CreateNodesContext } from '@nx/devkit'; import { createNodes } from './plugin'; import { TempFs } from 'nx/src/internal-testing-utils/temp-fs'; -jest.mock('@nuxt/kit', () => ({ - loadNuxtConfig: jest.fn().mockImplementation(() => { +jest.mock('vite', () => ({ + loadConfigFromFile: jest.fn().mockImplementation(() => { return Promise.resolve({ - path: 'nuxt.config.ts', + path: 'vite.config.ts', config: {}, dependencies: [], }); }), })); +jest.mock('@nuxt/kit', () => ({ + loadNuxtConfig: jest.fn().mockImplementation(() => { + return Promise.resolve({ + buildDir: '../dist/my-app/.nuxt', + }); + }), +})); + jest.mock('../utils/executor-utils', () => ({ loadNuxtKitDynamicImport: jest.fn().mockResolvedValue({ loadNuxtConfig: jest.fn().mockResolvedValue({ - path: 'nuxt.config.ts', - config: {}, - dependencies: [], + buildDir: '../dist/my-app/.nuxt', }), }), })); - describe('@nx/nuxt/plugin', () => { let createNodesFunction = createNodes[1]; let context: CreateNodesContext; + describe('root project', () => { beforeEach(async () => { context = { diff --git a/packages/nuxt/src/plugins/plugin.ts b/packages/nuxt/src/plugins/plugin.ts index 29116dabb99499..08abb6e9091f87 100644 --- a/packages/nuxt/src/plugins/plugin.ts +++ b/packages/nuxt/src/plugins/plugin.ts @@ -4,18 +4,19 @@ import { CreateNodesContext, detectPackageManager, joinPathFragments, - offsetFromRoot, readJsonFile, TargetConfiguration, + workspaceRoot, writeJsonFile, } from '@nx/devkit'; -import { basename, dirname, join } from 'path'; +import { basename, dirname, isAbsolute, join, relative } from 'path'; import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory'; import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs'; import { existsSync, readdirSync } from 'fs'; import { loadNuxtKitDynamicImport } from '../utils/executor-utils'; import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes'; import { getLockFileName } from '@nx/js'; +import { loadConfigFromFile, UserConfig } from 'vite'; const cachePath = join(projectGraphCacheDirectory, 'nuxt.hash'); const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; @@ -90,11 +91,36 @@ async function buildNuxtTargets( options: NuxtPluginOptions, context: CreateNodesContext ) { + let viteConfig: + | { + path: string; + config: UserConfig; + dependencies: string[]; + } + | undefined; + if ( + existsSync( + joinPathFragments(context.workspaceRoot, projectRoot, 'vitest.config.ts') + ) + ) { + viteConfig = await loadConfigFromFile( + { + command: 'build', + mode: 'production', + }, + joinPathFragments(context.workspaceRoot, projectRoot, 'vitest.config.ts') + ); + } + const nuxtConfig: { buildDir: string; } = await getInfoFromNuxtConfig(configFilePath, context, projectRoot); - const { buildOutputs, testOutputs } = getOutputs(projectRoot, nuxtConfig); + const { buildOutputs, testOutputs } = getOutputs( + nuxtConfig, + viteConfig?.config, + projectRoot + ); const namedInputs = getNamedInputs(projectRoot, context); @@ -133,7 +159,7 @@ function buildTarget( dependsOn: [`^${buildTargetName}`], inputs: [ ...('production' in namedInputs - ? ['default', '^production'] + ? ['production', '^production'] : ['default', '^default']), { @@ -187,59 +213,69 @@ async function getInfoFromNuxtConfig( buildDir: string; }> { const { loadNuxtConfig } = await loadNuxtKitDynamicImport(); + const config = await loadNuxtConfig({ cwd: joinPathFragments(context.workspaceRoot, projectRoot), configFile: basename(configFilePath), }); + console.log('KATERINA Here is the shallow buildDir', config?.buildDir); + console.log('KATERINA Here is the config', config); + return { // to preserve only the relative path from the workspace root // because nuxt automatically prepends the rootDir to buildDir - buildDir: config?.buildDir?.replace(config?.rootDir, ''), + buildDir: config?.buildDir, }; } function getOutputs( - projectRoot: string, - nuxtConfig: { - buildDir: string; - } + nuxtConfig: { buildDir: string }, + viteConfig: UserConfig, + projectRoot: string ): { buildOutputs: string[]; - outputPath: string; testOutputs: string[]; - reportsDirectory: string; } { - const buildOutputs = ['{options.outputPath}']; - const testOutputs = ['{options.reportsDirectory}']; - - function getOutput(path: string, projectRoot: string): string { - if (path.startsWith('..')) { - return join('{workspaceRoot}', join(projectRoot, path)); - } else { - return join('{projectRoot}', path); - } - } + const reportsDirectory = + normalizeOutputPath( + viteConfig?.['test']?.coverage?.reportsDirectory, + projectRoot + ) ?? '{workspaceRoot}/coverage/{projectRoot}'; - let distPath = undefined; + let nuxtBuildDir = nuxtConfig?.buildDir; if (nuxtConfig?.buildDir && basename(nuxtConfig?.buildDir) === '.nuxt') { // buildDir will most probably be `../dist/my-app/.nuxt` // we want the "general" outputPath to be `../dist/my-app` - distPath = nuxtConfig.buildDir.replace(basename(nuxtConfig.buildDir), ''); - buildOutputs.push(getOutput(distPath, projectRoot)); + nuxtBuildDir = nuxtConfig.buildDir.replace( + basename(nuxtConfig.buildDir), + '' + ); } + const buildOutputPath = + normalizeOutputPath(nuxtBuildDir, projectRoot) ?? + '{workspaceRoot}/dist/{projectRoot}'; - const outputPath = distPath ?? joinPathFragments('dist', projectRoot); - - const reportsDirectory = joinPathFragments( - offsetFromRoot(projectRoot), - 'coverage', - projectRoot - ); - - testOutputs.push(getOutput(reportsDirectory, projectRoot)); + return { + buildOutputs: [buildOutputPath], + testOutputs: [reportsDirectory], + }; +} - return { buildOutputs, outputPath, testOutputs, reportsDirectory }; +function normalizeOutputPath( + outputPath: string | undefined, + projectRoot: string +): string | undefined { + if (!outputPath) return undefined; + if (isAbsolute(outputPath)) { + return `{workspaceRoot}/${relative(workspaceRoot, outputPath)}`; + } else { + if (outputPath.startsWith('..')) { + return join('{workspaceRoot}', join(projectRoot, outputPath)); + } else { + return outputPath; + } + } } function normalizeOptions(options: NuxtPluginOptions): NuxtPluginOptions { diff --git a/packages/vite/src/plugins/__snapshots__/plugin.spec.ts.snap b/packages/vite/src/plugins/__snapshots__/plugin.spec.ts.snap index 33412087850cec..693e374b8492ca 100644 --- a/packages/vite/src/plugins/__snapshots__/plugin.spec.ts.snap +++ b/packages/vite/src/plugins/__snapshots__/plugin.spec.ts.snap @@ -25,7 +25,7 @@ exports[`@nx/vite/plugin not root project should create nodes 1`] = ` "cwd": "my-app", }, "outputs": [ - "{options.outputPath}", + "{workspaceRoot}/dist/{projectRoot}", ], }, "my-serve": { @@ -62,7 +62,7 @@ exports[`@nx/vite/plugin not root project should create nodes 1`] = ` "cwd": "my-app", }, "outputs": [ - "{options.reportsDirectory}", + "{workspaceRoot}/coverage/{projectRoot}", ], }, }, @@ -96,7 +96,7 @@ exports[`@nx/vite/plugin root project should create nodes 1`] = ` "cwd": ".", }, "outputs": [ - "{options.outputPath}", + "{workspaceRoot}/dist/{projectRoot}", ], }, "preview": { @@ -133,7 +133,7 @@ exports[`@nx/vite/plugin root project should create nodes 1`] = ` "cwd": ".", }, "outputs": [ - "{options.reportsDirectory}", + "{workspaceRoot}/coverage/{projectRoot}", ], }, }, diff --git a/packages/vite/src/plugins/plugin.ts b/packages/vite/src/plugins/plugin.ts index 71ef40f80db057..c51d0163ec979f 100644 --- a/packages/vite/src/plugins/plugin.ts +++ b/packages/vite/src/plugins/plugin.ts @@ -9,7 +9,7 @@ import { workspaceRoot, writeJsonFile, } from '@nx/devkit'; -import { dirname, isAbsolute, join, relative, resolve } from 'path'; +import { dirname, isAbsolute, join, relative } from 'path'; import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs'; import { loadConfigFromFile, UserConfig } from 'vite'; import { existsSync, readdirSync } from 'fs'; @@ -101,8 +101,8 @@ async function buildViteTargets( ); const { buildOutputs, testOutputs } = getOutputs( - projectRoot, - viteConfig?.config + viteConfig?.config, + projectRoot ); const namedInputs = getNamedInputs(projectRoot, context); @@ -213,35 +213,42 @@ function serveStaticTarget(options: VitePluginOptions) { } function getOutputs( - projectRoot: string, - viteConfig: UserConfig + viteConfig: UserConfig, + projectRoot: string ): { buildOutputs: string[]; testOutputs: string[]; } { const { build, test } = viteConfig; - const buildOutputs = ['{options.outputPath}']; - const testOutputs = ['{options.reportsDirectory}']; - - function getOutput(path: string, projectRoot: string): string { - if (path.startsWith('..')) { - return join('{workspaceRoot}', join(projectRoot, path)); - } else if (isAbsolute(resolve(path))) { - return `{workspaceRoot}/${relative(workspaceRoot, path)}`; - } else { - return join('{projectRoot}', path); - } - } - if (build?.outDir) { - buildOutputs.push(getOutput(build.outDir, projectRoot)); - } + const buildOutputPath = + normalizeOutputPath(build?.outDir, projectRoot) ?? + '{workspaceRoot}/dist/{projectRoot}'; - if (test?.coverage?.reportsDirectory) { - testOutputs.push(getOutput(test.coverage.reportsDirectory, projectRoot)); - } + const reportsDirectoryPath = + normalizeOutputPath(test?.coverage?.reportsDirectory, projectRoot) ?? + '{workspaceRoot}/coverage/{projectRoot}'; - return { buildOutputs, testOutputs }; + return { + buildOutputs: [buildOutputPath], + testOutputs: [reportsDirectoryPath], + }; +} + +function normalizeOutputPath( + outputPath: string | undefined, + projectRoot: string +): string | undefined { + if (!outputPath) return undefined; + if (isAbsolute(outputPath)) { + return `{workspaceRoot}/${relative(workspaceRoot, outputPath)}`; + } else { + if (outputPath.startsWith('..')) { + return join('{workspaceRoot}', join(projectRoot, outputPath)); + } else { + return outputPath; + } + } } function normalizeOptions(options: VitePluginOptions): VitePluginOptions {