Skip to content

Commit

Permalink
feat(vite): nodes for build, serve, test, preview targets (#20086)
Browse files Browse the repository at this point in the history
  • Loading branch information
mandarini committed Nov 30, 2023
1 parent 5a47eaf commit 83db767
Show file tree
Hide file tree
Showing 19 changed files with 846 additions and 116 deletions.
59 changes: 59 additions & 0 deletions e2e/vite/src/vite-pcv3.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { cleanupProject, newProject, runCLI, uniq } from '@nx/e2e/utils';

const myApp = uniq('my-app');

describe('@nx/vite/plugin', () => {
let proj: string;
let originalEnv: string;

beforeAll(() => {
originalEnv = process.env.NX_PCV3;
process.env.NX_PCV3 = 'true';
});

afterAll(() => {
process.env.NODE_ENV = originalEnv;
});

describe('build and test React Vite app', () => {
beforeAll(() => {
proj = newProject();
runCLI(
`generate @nx/react:app ${myApp} --bundler=vite --unitTestRunner=vitest`
);
});

afterAll(() => cleanupProject());

it('should build application', () => {
const result = runCLI(`build ${myApp}`);
expect(result).toContain('Successfully ran target build');
}, 200_000);

it('should test application', () => {
const result = runCLI(`test ${myApp}`);
expect(result).toContain('Successfully ran target test');
}, 200_000);
});

describe('build and test Vue app', () => {
beforeAll(() => {
proj = newProject();
runCLI(`generate @nx/vue:app ${myApp} --unitTestRunner=vitest`);
});

afterAll(() => {
cleanupProject();
});

it('should build application', () => {
const result = runCLI(`build ${myApp}`);
expect(result).toContain('Successfully ran target build');
}, 200_000);

it('should test application', () => {
const result = runCLI(`test ${myApp}`);
expect(result).toContain('Successfully ran target test');
}, 200_000);
});
});
15 changes: 15 additions & 0 deletions packages/react/src/generators/application/application.pcv3.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
import {
getProjects,
readNxJson,
readProjectConfiguration,
Tree,
Expand Down Expand Up @@ -33,6 +34,7 @@ describe('react app generator (PCv3)', () => {
const nxJson = readNxJson(appTree);
nxJson.plugins ??= [];
nxJson.plugins.push('@nx/webpack/plugin');
nxJson.plugins.push('@nx/vite/plugin');
updateNxJson(appTree, nxJson);
});

Expand All @@ -57,4 +59,17 @@ describe('react app generator (PCv3)', () => {
`assets: ['./src/favicon.ico', './src/assets']`
);
});

it('should not add targets for vite', async () => {
await applicationGenerator(appTree, {
...schema,
name: 'my-vite-app',
bundler: 'vite',
});
const projects = getProjects(appTree);
expect(projects.get('my-vite-app').targets.build).toBeUndefined();
expect(projects.get('my-vite-app').targets.serve).toBeUndefined();
expect(projects.get('my-vite-app').targets.preview).toBeUndefined();
expect(projects.get('my-vite-app').targets.test).toBeUndefined();
});
});
6 changes: 5 additions & 1 deletion packages/react/src/generators/application/lib/add-e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { webStaticServeGenerator } from '@nx/web';

import { nxVersion } from '../../../utils/versions';
import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
import { hasVitePlugin } from '../../../utils/has-vite-plugin';
import { NormalizedSchema } from '../schema';

export async function addE2e(
Expand All @@ -17,7 +18,10 @@ export async function addE2e(
): Promise<GeneratorCallback> {
switch (options.e2eTestRunner) {
case 'cypress': {
if (!hasWebpackPlugin(tree)) {
if (
(options.bundler === 'webpack' && !hasWebpackPlugin(tree)) ||
(options.bundler === 'vite' && !hasVitePlugin(tree))
) {
webStaticServeGenerator(tree, {
buildTarget: `${options.projectName}:build`,
targetName: 'serve-static',
Expand Down
10 changes: 10 additions & 0 deletions packages/react/src/utils/has-vite-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { readNxJson, Tree } from '@nx/devkit';

export function hasVitePlugin(tree: Tree) {
const nxJson = readNxJson(tree);
return !!nxJson.plugins?.some((p) =>
typeof p === 'string'
? p === '@nx/vite/plugin'
: p.plugin === '@nx/vite/plugin'
);
}
10 changes: 10 additions & 0 deletions packages/vite/migrations.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ import json = require('./migrations.json');
import { assertValidMigrationPaths } from '@nx/devkit/internal-testing-utils';
import { MigrationsJson } from '@nx/devkit';

jest.mock('vite', () => ({
loadConfigFromFile: jest.fn().mockImplementation(() => {
return Promise.resolve({
path: 'vite.config.ts',
config: {},
dependencies: [],
});
}),
}));

describe('vite migrations', () => {
assertValidMigrationPaths(json as MigrationsJson, __dirname);
});
3 changes: 2 additions & 1 deletion packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
"migrations": "./migrations.json"
},
"dependencies": {
"@nx/devkit": "file:../devkit",
"@phenomnomnominal/tsquery": "~5.0.1",
"@swc/helpers": "~0.5.0",
"enquirer": "~2.3.6",
"@nx/devkit": "file:../devkit",
"@nx/js": "file:../js",
"tsconfig-paths": "^4.1.2"
},
Expand All @@ -45,6 +45,7 @@
},
"exports": {
".": "./index.js",
"./plugin": "./plugin.js",
"./package.json": "./package.json",
"./migrations.json": "./migrations.json",
"./generators.json": "./generators.json",
Expand Down
5 changes: 5 additions & 0 deletions packages/vite/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export {
createNodes,
VitePluginOptions,
createDependencies,
} from './src/plugins/plugin';
30 changes: 20 additions & 10 deletions packages/vite/src/generators/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
formatFiles,
GeneratorCallback,
joinPathFragments,
readNxJson,
readProjectConfiguration,
runTasksInSerial,
Tree,
Expand Down Expand Up @@ -164,19 +165,27 @@ export async function viteConfigurationGenerator(
});
tasks.push(initTask);

if (!projectAlreadyHasViteTargets.build) {
addOrChangeBuildTarget(tree, schema, buildTargetName);
}
const nxJson = readNxJson(tree);
const hasPlugin = nxJson.plugins?.some((p) =>
typeof p === 'string'
? p === '@nx/vite/plugin'
: p.plugin === '@nx/vite/plugin'
);

if (!schema.includeLib) {
if (!projectAlreadyHasViteTargets.serve) {
addOrChangeServeTarget(tree, schema, serveTargetName);
if (!hasPlugin) {
if (!projectAlreadyHasViteTargets.build) {
addOrChangeBuildTarget(tree, schema, buildTargetName);
}
if (!projectAlreadyHasViteTargets.preview) {
addPreviewTarget(tree, schema, serveTargetName);

if (!schema.includeLib) {
if (!projectAlreadyHasViteTargets.serve) {
addOrChangeServeTarget(tree, schema, serveTargetName);
}
if (!projectAlreadyHasViteTargets.preview) {
addPreviewTarget(tree, schema, serveTargetName);
}
}
}

if (projectType === 'library') {
// update tsconfig.lib.json to include vite/client
updateJson(
Expand Down Expand Up @@ -225,7 +234,8 @@ export async function viteConfigurationGenerator(
],
plugins: ['react()'],
},
false
false,
undefined
);
} else {
createOrEditViteConfig(tree, schema, false, projectAlreadyHasViteTargets);
Expand Down
86 changes: 10 additions & 76 deletions packages/vite/src/generators/init/init.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,13 @@
import {
addDependenciesToPackageJson,
logger,
readJson,
readNxJson,
runTasksInSerial,
Tree,
updateJson,
updateNxJson,
} from '@nx/devkit';
import { readNxJson, runTasksInSerial, Tree, updateNxJson } from '@nx/devkit';

import { initGenerator as jsInitGenerator } from '@nx/js';

import {
edgeRuntimeVmVersion,
happyDomVersion,
jsdomVersion,
nxVersion,
vitePluginDtsVersion,
vitePluginReactSwcVersion,
vitePluginReactVersion,
vitestVersion,
viteVersion,
} from '../../utils/versions';
import { InitGeneratorSchema } from './schema';

function checkDependenciesInstalled(host: Tree, schema: InitGeneratorSchema) {
const packageJson = readJson(host, 'package.json');
const devDependencies = {};
const dependencies = {};
packageJson.dependencies = packageJson.dependencies || {};
packageJson.devDependencies = packageJson.devDependencies || {};

// base deps
devDependencies['@nx/vite'] = nxVersion;
devDependencies['vite'] = viteVersion;
devDependencies['vitest'] = vitestVersion;
devDependencies['@vitest/ui'] = vitestVersion;

if (schema.testEnvironment === 'jsdom') {
devDependencies['jsdom'] = jsdomVersion;
} else if (schema.testEnvironment === 'happy-dom') {
devDependencies['happy-dom'] = happyDomVersion;
} else if (schema.testEnvironment === 'edge-runtime') {
devDependencies['@edge-runtime/vm'] = edgeRuntimeVmVersion;
} else if (schema.testEnvironment !== 'node' && schema.testEnvironment) {
logger.info(
`A custom environment was provided: ${schema.testEnvironment}. You need to install it manually.`
);
}

if (schema.uiFramework === 'react') {
if (schema.compiler === 'swc') {
devDependencies['@vitejs/plugin-react-swc'] = vitePluginReactSwcVersion;
} else {
devDependencies['@vitejs/plugin-react'] = vitePluginReactVersion;
}
}

if (schema.includeLib) {
devDependencies['vite-plugin-dts'] = vitePluginDtsVersion;
}

return addDependenciesToPackageJson(host, dependencies, devDependencies);
}

function moveToDevDependencies(tree: Tree) {
updateJson(tree, 'package.json', (packageJson) => {
packageJson.dependencies = packageJson.dependencies || {};
packageJson.devDependencies = packageJson.devDependencies || {};

if (packageJson.dependencies['@nx/vite']) {
packageJson.devDependencies['@nx/vite'] =
packageJson.dependencies['@nx/vite'];
delete packageJson.dependencies['@nx/vite'];
}
return packageJson;
});
}
import {
addPlugin,
checkDependenciesInstalled,
moveToDevDependencies,
} from './lib/utils';

export function updateNxJsonSettings(tree: Tree) {
const nxJson = readNxJson(tree);
Expand Down Expand Up @@ -127,7 +58,10 @@ export async function initGenerator(tree: Tree, schema: InitGeneratorSchema) {
tsConfigName: schema.rootProject ? 'tsconfig.json' : 'tsconfig.base.json',
})
);

const addPlugins = process.env.NX_PCV3 === 'true';
if (addPlugins) {
addPlugin(tree);
}
tasks.push(checkDependenciesInstalled(tree, schema));
return runTasksInSerial(...tasks);
}
Expand Down

0 comments on commit 83db767

Please sign in to comment.