fix(vite): include vitest config in nodes plugin (#20887)

This commit is contained in:
Katerina Skroumpelou 2024-01-02 16:17:58 +02:00 committed by GitHub
parent d99e8e6aa5
commit f7d179522f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 136 additions and 144 deletions

View File

@ -36,9 +36,7 @@
"@nx/eslint": "file:../eslint", "@nx/eslint": "file:../eslint",
"@nx/vue": "file:../vue" "@nx/vue": "file:../vue"
}, },
"peerDependencies": { "peerDependencies": {},
"vite": "^5.0.0"
},
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} }

View File

@ -124,8 +124,7 @@ describe('app', () => {
const projectConfi = readProjectConfiguration(tree, name); const projectConfi = readProjectConfiguration(tree, name);
expect(projectConfi.targets.build).toBeUndefined(); expect(projectConfi.targets.build).toBeUndefined();
expect(projectConfi.targets.serve).toBeUndefined(); expect(projectConfi.targets.serve).toBeUndefined();
// TODO(katerina): Enable once `@nx/vite/plugin` is released expect(projectConfi.targets.test).toBeUndefined();
// expect(projectConfi.targets.test).toBeUndefined();
}); });
}); });
}); });

View File

@ -32,6 +32,10 @@ describe('init', () => {
options: { buildTargetName: 'build', serveTargetName: 'serve' }, options: { buildTargetName: 'build', serveTargetName: 'serve' },
plugin: '@nx/nuxt/plugin', plugin: '@nx/nuxt/plugin',
}, },
{
options: { testTargetName: 'test' },
plugin: '@nx/vite/plugin',
},
]); ]);
}); });
}); });

View File

@ -24,7 +24,7 @@ import { InitSchema } from '../schema';
export function updateDependencies(host: Tree, schema: InitSchema) { export function updateDependencies(host: Tree, schema: InitSchema) {
let devDependencies: { [key: string]: string } = { let devDependencies: { [key: string]: string } = {
'@nx/nuxt': nxVersion, '@nx/nuxt': nxVersion,
'@nx/vite': nxVersion, // needed for the nxViteTsPaths plugin '@nx/vite': nxVersion, // needed for the nxViteTsPaths plugin and @nx/vite/plugin
'@nuxt/devtools': nuxtDevtoolsVersion, '@nuxt/devtools': nuxtDevtoolsVersion,
'@nuxt/kit': nuxtVersion, '@nuxt/kit': nuxtVersion,
'@nuxt/ui-templates': nuxtUiTemplatesVersion, '@nuxt/ui-templates': nuxtUiTemplatesVersion,
@ -64,23 +64,44 @@ export function addPlugin(tree: Tree) {
const nxJson = readNxJson(tree); const nxJson = readNxJson(tree);
nxJson.plugins ??= []; nxJson.plugins ??= [];
let hasNxNuxtPlugin = false;
let hasNxVitePlugin = false;
for (const plugin of nxJson.plugins) { for (const plugin of nxJson.plugins) {
if ( if (
typeof plugin === 'string' typeof plugin === 'string'
? plugin === '@nx/nuxt/plugin' ? plugin === '@nx/nuxt/plugin'
: plugin.plugin === '@nx/nuxt/plugin' : plugin.plugin === '@nx/nuxt/plugin'
) { ) {
return; hasNxNuxtPlugin = true;
}
if (
typeof plugin === 'string'
? plugin === '@nx/vite/plugin'
: plugin.plugin === '@nx/vite/plugin'
) {
hasNxVitePlugin = true;
} }
} }
if (!hasNxNuxtPlugin) {
nxJson.plugins.push({ nxJson.plugins.push({
plugin: '@nx/nuxt/plugin', plugin: '@nx/nuxt/plugin',
options: { options: {
buildTargetName: 'build', buildTargetName: 'build',
testTargetName: 'test',
serveTargetName: 'serve', serveTargetName: 'serve',
}, },
}); });
}
if (!hasNxVitePlugin) {
nxJson.plugins.push({
plugin: '@nx/vite/plugin',
options: {
testTargetName: 'test',
},
});
}
updateNxJson(tree, nxJson); updateNxJson(tree, nxJson);
} }

View File

@ -34,25 +34,6 @@ exports[`@nx/nuxt/plugin not root project should create nodes 1`] = `
"cwd": "my-app", "cwd": "my-app",
}, },
}, },
"test": {
"cache": true,
"command": "vitest run",
"inputs": [
"default",
"^production",
{
"externalDependencies": [
"vitest",
],
},
],
"options": {
"cwd": "my-app",
},
"outputs": [
"{workspaceRoot}/coverage/{projectRoot}",
],
},
}, },
}, },
}, },
@ -93,25 +74,6 @@ exports[`@nx/nuxt/plugin root project should create nodes 1`] = `
"cwd": ".", "cwd": ".",
}, },
}, },
"test": {
"cache": true,
"command": "vitest run",
"inputs": [
"default",
"^production",
{
"externalDependencies": [
"vitest",
],
},
],
"options": {
"cwd": ".",
},
"outputs": [
"{projectRoot}/coverage",
],
},
}, },
}, },
}, },

View File

@ -2,16 +2,6 @@ import { CreateNodesContext } from '@nx/devkit';
import { createNodes } from './plugin'; import { createNodes } from './plugin';
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs'; import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
jest.mock('vite', () => ({
loadConfigFromFile: jest.fn().mockImplementation(() => {
return Promise.resolve({
path: 'vite.config.ts',
config: {},
dependencies: [],
});
}),
}));
jest.mock('@nuxt/kit', () => ({ jest.mock('@nuxt/kit', () => ({
loadNuxtConfig: jest.fn().mockImplementation(() => { loadNuxtConfig: jest.fn().mockImplementation(() => {
return Promise.resolve({ return Promise.resolve({

View File

@ -16,7 +16,6 @@ import { existsSync, readdirSync } from 'fs';
import { loadNuxtKitDynamicImport } from '../utils/executor-utils'; import { loadNuxtKitDynamicImport } from '../utils/executor-utils';
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes'; import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
import { getLockFileName } from '@nx/js'; import { getLockFileName } from '@nx/js';
import { loadConfigFromFile, UserConfig } from 'vite';
const cachePath = join(projectGraphCacheDirectory, 'nuxt.hash'); const cachePath = join(projectGraphCacheDirectory, 'nuxt.hash');
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};
@ -47,7 +46,6 @@ export const createDependencies: CreateDependencies = () => {
export interface NuxtPluginOptions { export interface NuxtPluginOptions {
buildTargetName?: string; buildTargetName?: string;
serveTargetName?: string; serveTargetName?: string;
testTargetName?: string;
} }
export const createNodes: CreateNodes<NuxtPluginOptions> = [ export const createNodes: CreateNodes<NuxtPluginOptions> = [
@ -91,34 +89,13 @@ async function buildNuxtTargets(
options: NuxtPluginOptions, options: NuxtPluginOptions,
context: CreateNodesContext 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: { const nuxtConfig: {
buildDir: string; buildDir: string;
} = await getInfoFromNuxtConfig(configFilePath, context, projectRoot); } = await getInfoFromNuxtConfig(configFilePath, context, projectRoot);
const { buildOutputs, testOutputs } = getOutputs( const { buildOutputs } = getOutputs(
nuxtConfig, nuxtConfig,
viteConfig?.config,
projectRoot projectRoot
); );
@ -135,12 +112,6 @@ async function buildNuxtTargets(
targets[options.serveTargetName] = serveTarget(projectRoot); targets[options.serveTargetName] = serveTarget(projectRoot);
targets[options.testTargetName] = testTarget(
namedInputs,
testOutputs,
projectRoot
);
return targets; return targets;
} }
@ -181,30 +152,6 @@ function serveTarget(projectRoot: string) {
return targetConfig; return targetConfig;
} }
function testTarget(
namedInputs: {
[inputName: string]: any[];
},
outputs: string[],
projectRoot: string
) {
return {
command: `vitest run`,
options: { cwd: projectRoot },
cache: true,
inputs: [
...('production' in namedInputs
? ['default', '^production']
: ['default', '^default']),
{
externalDependencies: ['vitest'],
},
],
outputs,
};
}
async function getInfoFromNuxtConfig( async function getInfoFromNuxtConfig(
configFilePath: string, configFilePath: string,
context: CreateNodesContext, context: CreateNodesContext,
@ -226,18 +173,10 @@ async function getInfoFromNuxtConfig(
function getOutputs( function getOutputs(
nuxtConfig: { buildDir: string }, nuxtConfig: { buildDir: string },
viteConfig: UserConfig,
projectRoot: string projectRoot: string
): { ): {
buildOutputs: string[]; buildOutputs: string[];
testOutputs: string[];
} { } {
const reportsDirectory = normalizeOutputPath(
viteConfig?.['test']?.coverage?.reportsDirectory,
projectRoot,
'coverage'
);
let nuxtBuildDir = nuxtConfig?.buildDir; let nuxtBuildDir = nuxtConfig?.buildDir;
if (nuxtConfig?.buildDir && basename(nuxtConfig?.buildDir) === '.nuxt') { if (nuxtConfig?.buildDir && basename(nuxtConfig?.buildDir) === '.nuxt') {
// buildDir will most probably be `../dist/my-app/.nuxt` // buildDir will most probably be `../dist/my-app/.nuxt`
@ -248,25 +187,23 @@ function getOutputs(
); );
} }
const buildOutputPath = const buildOutputPath =
normalizeOutputPath(nuxtBuildDir, projectRoot, 'dist') ?? normalizeOutputPath(nuxtBuildDir, projectRoot) ??
'{workspaceRoot}/dist/{projectRoot}'; '{workspaceRoot}/dist/{projectRoot}';
return { return {
buildOutputs: [buildOutputPath], buildOutputs: [buildOutputPath],
testOutputs: [reportsDirectory],
}; };
} }
function normalizeOutputPath( function normalizeOutputPath(
outputPath: string | undefined, outputPath: string | undefined,
projectRoot: string, projectRoot: string
path: 'coverage' | 'dist'
): string | undefined { ): string | undefined {
if (!outputPath) { if (!outputPath) {
if (projectRoot === '.') { if (projectRoot === '.') {
return `{projectRoot}/${path}`; return `{projectRoot}/dist`;
} else { } else {
return `{workspaceRoot}/${path}/{projectRoot}`; return `{workspaceRoot}/dist/{projectRoot}`;
} }
} else { } else {
if (isAbsolute(outputPath)) { if (isAbsolute(outputPath)) {
@ -285,6 +222,5 @@ function normalizeOptions(options: NuxtPluginOptions): NuxtPluginOptions {
options ??= {}; options ??= {};
options.buildTargetName ??= 'build'; options.buildTargetName ??= 'build';
options.serveTargetName ??= 'serve'; options.serveTargetName ??= 'serve';
options.testTargetName ??= 'test';
return options; return options;
} }

View File

@ -0,0 +1,32 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`@nx/vite/plugin root project should create nodes 1`] = `
{
"projects": {
".": {
"root": ".",
"targets": {
"test": {
"cache": true,
"command": "vitest run",
"inputs": [
"default",
"^production",
{
"externalDependencies": [
"vitest",
],
},
],
"options": {
"cwd": ".",
},
"outputs": [
"{projectRoot}/coverage",
],
},
},
},
},
}
`;

View File

@ -0,0 +1,48 @@
import { CreateNodesContext } from '@nx/devkit';
import { createNodes } from './plugin';
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
jest.mock('vite', () => ({
loadConfigFromFile: jest.fn().mockImplementation(() => {
return Promise.resolve({
path: 'vitest.config.ts',
config: {},
dependencies: [],
});
}),
}));
describe('@nx/vite/plugin', () => {
let createNodesFunction = createNodes[1];
let context: CreateNodesContext;
describe('root project', () => {
beforeEach(async () => {
context = {
nxJsonConfiguration: {
targetDefaults: {},
namedInputs: {
default: ['{projectRoot}/**/*'],
production: ['!{projectRoot}/**/*.spec.ts'],
},
},
workspaceRoot: '',
};
});
afterEach(() => {
jest.resetModules();
});
it('should create nodes', async () => {
const nodes = await createNodesFunction(
'vitest.config.ts',
{
testTargetName: 'test',
},
context
);
expect(nodes).toMatchSnapshot();
});
});
});

View File

@ -52,7 +52,7 @@ export const createDependencies: CreateDependencies = () => {
}; };
export const createNodes: CreateNodes<VitePluginOptions> = [ export const createNodes: CreateNodes<VitePluginOptions> = [
'**/vite.config.{js,ts}', '**/{vite,vitest}.config.{js,ts}',
async (configFilePath, options, context) => { async (configFilePath, options, context) => {
const projectRoot = dirname(configFilePath); const projectRoot = dirname(configFilePath);
// Do not create a project if package.json and project.json isn't there. // Do not create a project if package.json and project.json isn't there.
@ -109,6 +109,7 @@ async function buildViteTargets(
const targets: Record<string, TargetConfiguration> = {}; const targets: Record<string, TargetConfiguration> = {};
if (!configFilePath.includes('vitest.config')) {
targets[options.buildTargetName] = await buildTarget( targets[options.buildTargetName] = await buildTarget(
options.buildTargetName, options.buildTargetName,
namedInputs, namedInputs,
@ -120,14 +121,15 @@ async function buildViteTargets(
targets[options.previewTargetName] = previewTarget(projectRoot); targets[options.previewTargetName] = previewTarget(projectRoot);
targets[options.serveStaticTargetName] = serveStaticTarget(options) as {};
}
targets[options.testTargetName] = await testTarget( targets[options.testTargetName] = await testTarget(
namedInputs, namedInputs,
testOutputs, testOutputs,
projectRoot projectRoot
); );
targets[options.serveStaticTargetName] = serveStaticTarget(options) as {};
return targets; return targets;
} }