Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vite): nodes for build, serve, test, preview targets #20086

Merged
merged 2 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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);
});
});
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