feat(vite): nodes for build, serve, test, preview targets (#20086)
This commit is contained in:
parent
5a47eaf684
commit
83db767b27
59
e2e/vite/src/vite-pcv3.test.ts
Normal file
59
e2e/vite/src/vite-pcv3.test.ts
Normal file
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
||||||
import {
|
import {
|
||||||
|
getProjects,
|
||||||
readNxJson,
|
readNxJson,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
Tree,
|
Tree,
|
||||||
@ -33,6 +34,7 @@ describe('react app generator (PCv3)', () => {
|
|||||||
const nxJson = readNxJson(appTree);
|
const nxJson = readNxJson(appTree);
|
||||||
nxJson.plugins ??= [];
|
nxJson.plugins ??= [];
|
||||||
nxJson.plugins.push('@nx/webpack/plugin');
|
nxJson.plugins.push('@nx/webpack/plugin');
|
||||||
|
nxJson.plugins.push('@nx/vite/plugin');
|
||||||
updateNxJson(appTree, nxJson);
|
updateNxJson(appTree, nxJson);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,4 +59,17 @@ describe('react app generator (PCv3)', () => {
|
|||||||
`assets: ['./src/favicon.ico', './src/assets']`
|
`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();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { webStaticServeGenerator } from '@nx/web';
|
|||||||
|
|
||||||
import { nxVersion } from '../../../utils/versions';
|
import { nxVersion } from '../../../utils/versions';
|
||||||
import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
|
import { hasWebpackPlugin } from '../../../utils/has-webpack-plugin';
|
||||||
|
import { hasVitePlugin } from '../../../utils/has-vite-plugin';
|
||||||
import { NormalizedSchema } from '../schema';
|
import { NormalizedSchema } from '../schema';
|
||||||
|
|
||||||
export async function addE2e(
|
export async function addE2e(
|
||||||
@ -17,7 +18,10 @@ export async function addE2e(
|
|||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
switch (options.e2eTestRunner) {
|
switch (options.e2eTestRunner) {
|
||||||
case 'cypress': {
|
case 'cypress': {
|
||||||
if (!hasWebpackPlugin(tree)) {
|
if (
|
||||||
|
(options.bundler === 'webpack' && !hasWebpackPlugin(tree)) ||
|
||||||
|
(options.bundler === 'vite' && !hasVitePlugin(tree))
|
||||||
|
) {
|
||||||
webStaticServeGenerator(tree, {
|
webStaticServeGenerator(tree, {
|
||||||
buildTarget: `${options.projectName}:build`,
|
buildTarget: `${options.projectName}:build`,
|
||||||
targetName: 'serve-static',
|
targetName: 'serve-static',
|
||||||
|
|||||||
10
packages/react/src/utils/has-vite-plugin.ts
Normal file
10
packages/react/src/utils/has-vite-plugin.ts
Normal file
@ -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'
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -3,6 +3,16 @@ import json = require('./migrations.json');
|
|||||||
import { assertValidMigrationPaths } from '@nx/devkit/internal-testing-utils';
|
import { assertValidMigrationPaths } from '@nx/devkit/internal-testing-utils';
|
||||||
import { MigrationsJson } from '@nx/devkit';
|
import { MigrationsJson } from '@nx/devkit';
|
||||||
|
|
||||||
|
jest.mock('vite', () => ({
|
||||||
|
loadConfigFromFile: jest.fn().mockImplementation(() => {
|
||||||
|
return Promise.resolve({
|
||||||
|
path: 'vite.config.ts',
|
||||||
|
config: {},
|
||||||
|
dependencies: [],
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('vite migrations', () => {
|
describe('vite migrations', () => {
|
||||||
assertValidMigrationPaths(json as MigrationsJson, __dirname);
|
assertValidMigrationPaths(json as MigrationsJson, __dirname);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -29,10 +29,10 @@
|
|||||||
"migrations": "./migrations.json"
|
"migrations": "./migrations.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@nx/devkit": "file:../devkit",
|
||||||
"@phenomnomnominal/tsquery": "~5.0.1",
|
"@phenomnomnominal/tsquery": "~5.0.1",
|
||||||
"@swc/helpers": "~0.5.0",
|
"@swc/helpers": "~0.5.0",
|
||||||
"enquirer": "~2.3.6",
|
"enquirer": "~2.3.6",
|
||||||
"@nx/devkit": "file:../devkit",
|
|
||||||
"@nx/js": "file:../js",
|
"@nx/js": "file:../js",
|
||||||
"tsconfig-paths": "^4.1.2"
|
"tsconfig-paths": "^4.1.2"
|
||||||
},
|
},
|
||||||
@ -45,6 +45,7 @@
|
|||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./index.js",
|
".": "./index.js",
|
||||||
|
"./plugin": "./plugin.js",
|
||||||
"./package.json": "./package.json",
|
"./package.json": "./package.json",
|
||||||
"./migrations.json": "./migrations.json",
|
"./migrations.json": "./migrations.json",
|
||||||
"./generators.json": "./generators.json",
|
"./generators.json": "./generators.json",
|
||||||
|
|||||||
5
packages/vite/plugin.ts
Normal file
5
packages/vite/plugin.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export {
|
||||||
|
createNodes,
|
||||||
|
VitePluginOptions,
|
||||||
|
createDependencies,
|
||||||
|
} from './src/plugins/plugin';
|
||||||
@ -2,6 +2,7 @@ import {
|
|||||||
formatFiles,
|
formatFiles,
|
||||||
GeneratorCallback,
|
GeneratorCallback,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
|
readNxJson,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
@ -164,19 +165,27 @@ export async function viteConfigurationGenerator(
|
|||||||
});
|
});
|
||||||
tasks.push(initTask);
|
tasks.push(initTask);
|
||||||
|
|
||||||
if (!projectAlreadyHasViteTargets.build) {
|
const nxJson = readNxJson(tree);
|
||||||
addOrChangeBuildTarget(tree, schema, buildTargetName);
|
const hasPlugin = nxJson.plugins?.some((p) =>
|
||||||
}
|
typeof p === 'string'
|
||||||
|
? p === '@nx/vite/plugin'
|
||||||
|
: p.plugin === '@nx/vite/plugin'
|
||||||
|
);
|
||||||
|
|
||||||
if (!schema.includeLib) {
|
if (!hasPlugin) {
|
||||||
if (!projectAlreadyHasViteTargets.serve) {
|
if (!projectAlreadyHasViteTargets.build) {
|
||||||
addOrChangeServeTarget(tree, schema, serveTargetName);
|
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') {
|
if (projectType === 'library') {
|
||||||
// update tsconfig.lib.json to include vite/client
|
// update tsconfig.lib.json to include vite/client
|
||||||
updateJson(
|
updateJson(
|
||||||
@ -225,7 +234,8 @@ export async function viteConfigurationGenerator(
|
|||||||
],
|
],
|
||||||
plugins: ['react()'],
|
plugins: ['react()'],
|
||||||
},
|
},
|
||||||
false
|
false,
|
||||||
|
undefined
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
createOrEditViteConfig(tree, schema, false, projectAlreadyHasViteTargets);
|
createOrEditViteConfig(tree, schema, false, projectAlreadyHasViteTargets);
|
||||||
|
|||||||
@ -1,82 +1,13 @@
|
|||||||
import {
|
import { readNxJson, runTasksInSerial, Tree, updateNxJson } from '@nx/devkit';
|
||||||
addDependenciesToPackageJson,
|
|
||||||
logger,
|
|
||||||
readJson,
|
|
||||||
readNxJson,
|
|
||||||
runTasksInSerial,
|
|
||||||
Tree,
|
|
||||||
updateJson,
|
|
||||||
updateNxJson,
|
|
||||||
} from '@nx/devkit';
|
|
||||||
|
|
||||||
import { initGenerator as jsInitGenerator } from '@nx/js';
|
import { initGenerator as jsInitGenerator } from '@nx/js';
|
||||||
|
|
||||||
import {
|
|
||||||
edgeRuntimeVmVersion,
|
|
||||||
happyDomVersion,
|
|
||||||
jsdomVersion,
|
|
||||||
nxVersion,
|
|
||||||
vitePluginDtsVersion,
|
|
||||||
vitePluginReactSwcVersion,
|
|
||||||
vitePluginReactVersion,
|
|
||||||
vitestVersion,
|
|
||||||
viteVersion,
|
|
||||||
} from '../../utils/versions';
|
|
||||||
import { InitGeneratorSchema } from './schema';
|
import { InitGeneratorSchema } from './schema';
|
||||||
|
import {
|
||||||
function checkDependenciesInstalled(host: Tree, schema: InitGeneratorSchema) {
|
addPlugin,
|
||||||
const packageJson = readJson(host, 'package.json');
|
checkDependenciesInstalled,
|
||||||
const devDependencies = {};
|
moveToDevDependencies,
|
||||||
const dependencies = {};
|
} from './lib/utils';
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateNxJsonSettings(tree: Tree) {
|
export function updateNxJsonSettings(tree: Tree) {
|
||||||
const nxJson = readNxJson(tree);
|
const nxJson = readNxJson(tree);
|
||||||
@ -127,7 +58,10 @@ export async function initGenerator(tree: Tree, schema: InitGeneratorSchema) {
|
|||||||
tsConfigName: schema.rootProject ? 'tsconfig.json' : 'tsconfig.base.json',
|
tsConfigName: schema.rootProject ? 'tsconfig.json' : 'tsconfig.base.json',
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
const addPlugins = process.env.NX_PCV3 === 'true';
|
||||||
|
if (addPlugins) {
|
||||||
|
addPlugin(tree);
|
||||||
|
}
|
||||||
tasks.push(checkDependenciesInstalled(tree, schema));
|
tasks.push(checkDependenciesInstalled(tree, schema));
|
||||||
return runTasksInSerial(...tasks);
|
return runTasksInSerial(...tasks);
|
||||||
}
|
}
|
||||||
|
|||||||
122
packages/vite/src/generators/init/lib/utils.ts
Normal file
122
packages/vite/src/generators/init/lib/utils.ts
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import {
|
||||||
|
addDependenciesToPackageJson,
|
||||||
|
logger,
|
||||||
|
readJson,
|
||||||
|
readNxJson,
|
||||||
|
Tree,
|
||||||
|
updateJson,
|
||||||
|
updateNxJson,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
|
||||||
|
import {
|
||||||
|
edgeRuntimeVmVersion,
|
||||||
|
happyDomVersion,
|
||||||
|
jsdomVersion,
|
||||||
|
nxVersion,
|
||||||
|
vitePluginDtsVersion,
|
||||||
|
vitePluginReactSwcVersion,
|
||||||
|
vitePluginReactVersion,
|
||||||
|
vitestVersion,
|
||||||
|
viteVersion,
|
||||||
|
} from '../../../utils/versions';
|
||||||
|
import { InitGeneratorSchema } from '../schema';
|
||||||
|
|
||||||
|
export 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
export 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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createVitestConfig(tree: Tree) {
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
|
||||||
|
const productionFileSet = nxJson.namedInputs?.production;
|
||||||
|
if (productionFileSet) {
|
||||||
|
productionFileSet.push(
|
||||||
|
'!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)',
|
||||||
|
'!{projectRoot}/tsconfig.spec.json'
|
||||||
|
);
|
||||||
|
|
||||||
|
nxJson.namedInputs.production = Array.from(new Set(productionFileSet));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNxJson(tree, nxJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addPlugin(tree: Tree) {
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
nxJson.plugins ??= [];
|
||||||
|
|
||||||
|
for (const plugin of nxJson.plugins) {
|
||||||
|
if (
|
||||||
|
typeof plugin === 'string'
|
||||||
|
? plugin === '@nx/vite/plugin'
|
||||||
|
: plugin.plugin === '@nx/vite/plugin'
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nxJson.plugins.push({
|
||||||
|
plugin: '@nx/vite/plugin',
|
||||||
|
options: {
|
||||||
|
buildTargetName: 'build',
|
||||||
|
previewTargetName: 'preview',
|
||||||
|
testTargetName: 'test',
|
||||||
|
serveTargetName: 'serve',
|
||||||
|
serveStaticTargetName: 'serve-static',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
updateNxJson(tree, nxJson);
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ import {
|
|||||||
GeneratorCallback,
|
GeneratorCallback,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
offsetFromRoot,
|
offsetFromRoot,
|
||||||
|
readNxJson,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
@ -42,10 +43,20 @@ export async function vitestGenerator(
|
|||||||
findExistingTargetsInProject(targets).validFoundTargetName.test ??
|
findExistingTargetsInProject(targets).validFoundTargetName.test ??
|
||||||
'test';
|
'test';
|
||||||
|
|
||||||
if (!hasPlugin) {
|
const nxJson = readNxJson(tree);
|
||||||
|
const hasPluginCheck = nxJson.plugins?.some(
|
||||||
|
(p) =>
|
||||||
|
(typeof p === 'string'
|
||||||
|
? p === '@nx/vite/plugin'
|
||||||
|
: p.plugin === '@nx/vite/plugin') || hasPlugin
|
||||||
|
);
|
||||||
|
if (!hasPluginCheck) {
|
||||||
|
const testTarget =
|
||||||
|
schema.testTarget ??
|
||||||
|
findExistingTargetsInProject(targets).validFoundTargetName.test ??
|
||||||
|
'test';
|
||||||
addOrChangeTestTarget(tree, schema, testTarget);
|
addOrChangeTestTarget(tree, schema, testTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
const initTask = await initGenerator(tree, {
|
const initTask = await initGenerator(tree, {
|
||||||
uiFramework: schema.uiFramework,
|
uiFramework: schema.uiFramework,
|
||||||
testEnvironment: schema.testEnvironment,
|
testEnvironment: schema.testEnvironment,
|
||||||
|
|||||||
@ -36,24 +36,26 @@ function findAllProjectsWithViteConfig(tree: Tree): void {
|
|||||||
);
|
);
|
||||||
let startOfProjects, endOfProjects;
|
let startOfProjects, endOfProjects;
|
||||||
|
|
||||||
defineConfig?.[0]?.getChildren().forEach((defineConfigContentNode) => {
|
defineConfig?.[0]
|
||||||
// Make sure it's the one we are looking for
|
?.getChildren()
|
||||||
// We cannot assume that it's called tsConfigPaths
|
.forEach((defineConfigContentNode: any) => {
|
||||||
// So make sure it includes `projects` and `root`
|
// Make sure it's the one we are looking for
|
||||||
if (
|
// We cannot assume that it's called tsConfigPaths
|
||||||
defineConfigContentNode.getText().includes('projects') &&
|
// So make sure it includes `projects` and `root`
|
||||||
defineConfigContentNode.getText().includes('root')
|
if (
|
||||||
) {
|
defineConfigContentNode.getText().includes('projects') &&
|
||||||
findNodes(defineConfigContentNode, [
|
defineConfigContentNode.getText().includes('root')
|
||||||
ts.SyntaxKind.PropertyAssignment,
|
) {
|
||||||
]).forEach((nodePA) => {
|
findNodes(defineConfigContentNode, [
|
||||||
if (nodePA.getText().startsWith('projects')) {
|
ts.SyntaxKind.PropertyAssignment,
|
||||||
startOfProjects = nodePA.getStart();
|
]).forEach((nodePA) => {
|
||||||
endOfProjects = nodePA.getEnd();
|
if (nodePA.getText().startsWith('projects')) {
|
||||||
}
|
startOfProjects = nodePA.getStart();
|
||||||
});
|
endOfProjects = nodePA.getEnd();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (startOfProjects && endOfProjects) {
|
if (startOfProjects && endOfProjects) {
|
||||||
newContents = applyChangesToString(newContents, [
|
newContents = applyChangesToString(newContents, [
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { Tree, getProjects, joinPathFragments } from '@nx/devkit';
|
|||||||
import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils';
|
import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils';
|
||||||
import { ViteBuildExecutorOptions } from '../../executors/build/schema';
|
import { ViteBuildExecutorOptions } from '../../executors/build/schema';
|
||||||
import { tsquery } from '@phenomnomnominal/tsquery';
|
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||||
import { ImportDeclaration } from 'typescript';
|
|
||||||
|
|
||||||
export default function update(tree: Tree) {
|
export default function update(tree: Tree) {
|
||||||
const projects = getProjects(tree);
|
const projects = getProjects(tree);
|
||||||
@ -20,7 +19,7 @@ export default function update(tree: Tree) {
|
|||||||
const configContents = tree.read(config, 'utf-8');
|
const configContents = tree.read(config, 'utf-8');
|
||||||
|
|
||||||
const oldTsConfigPathPlugin =
|
const oldTsConfigPathPlugin =
|
||||||
tsquery.query<ImportDeclaration>(
|
tsquery.query(
|
||||||
configContents,
|
configContents,
|
||||||
'ImportDeclaration:has(StringLiteral[value="vite-tsconfig-paths"])'
|
'ImportDeclaration:has(StringLiteral[value="vite-tsconfig-paths"])'
|
||||||
) ?? [];
|
) ?? [];
|
||||||
@ -30,7 +29,7 @@ export default function update(tree: Tree) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const importName =
|
const importName =
|
||||||
oldTsConfigPathPlugin[0]?.importClause?.name?.text ??
|
oldTsConfigPathPlugin[0]?.['importClause']?.name?.text ??
|
||||||
'viteTsConfigPaths';
|
'viteTsConfigPaths';
|
||||||
const updatedContent = tsquery.replace(
|
const updatedContent = tsquery.replace(
|
||||||
configContents,
|
configContents,
|
||||||
|
|||||||
137
packages/vite/src/plugins/__snapshots__/plugin.spec.ts.snap
Normal file
137
packages/vite/src/plugins/__snapshots__/plugin.spec.ts.snap
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`@nx/vite/plugin not root project should create nodes 1`] = `
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"my-app": {
|
||||||
|
"root": "my-app",
|
||||||
|
"targets": {
|
||||||
|
"build-something": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "vite build",
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"vite",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "my-app",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{options.outputPath}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"my-serve": {
|
||||||
|
"command": "vite serve",
|
||||||
|
"options": {
|
||||||
|
"cwd": "my-app",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"preview-site": {
|
||||||
|
"command": "vite preview",
|
||||||
|
"options": {
|
||||||
|
"cwd": "my-app",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"serve-static": {
|
||||||
|
"executor": "@nx/web:file-server",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "build-something",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"vitest": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "vitest run",
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"vitest",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "my-app",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{options.reportsDirectory}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`@nx/vite/plugin root project should create nodes 1`] = `
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
".": {
|
||||||
|
"root": ".",
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "vite build",
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"vite",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{options.outputPath}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"preview": {
|
||||||
|
"command": "vite preview",
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"command": "vite serve",
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"serve-static": {
|
||||||
|
"executor": "@nx/web:file-server",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "build",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "vitest run",
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"vitest",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": ".",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{options.reportsDirectory}",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
93
packages/vite/src/plugins/plugin.spec.ts
Normal file
93
packages/vite/src/plugins/plugin.spec.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
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: 'vite.config.ts',
|
||||||
|
config: {},
|
||||||
|
dependencies: [],
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('@nx/vite/plugin', () => {
|
||||||
|
let createNodesFunction = createNodes[1];
|
||||||
|
let context: CreateNodesContext;
|
||||||
|
describe('root project', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
context = {
|
||||||
|
nxJsonConfiguration: {
|
||||||
|
namedInputs: {
|
||||||
|
default: ['{projectRoot}/**/*'],
|
||||||
|
production: ['!{projectRoot}/**/*.spec.ts'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
workspaceRoot: '',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create nodes', async () => {
|
||||||
|
const nodes = await createNodesFunction(
|
||||||
|
'vite.config.ts',
|
||||||
|
{
|
||||||
|
buildTargetName: 'build',
|
||||||
|
serveTargetName: 'serve',
|
||||||
|
previewTargetName: 'preview',
|
||||||
|
testTargetName: 'test',
|
||||||
|
serveStaticTargetName: 'serve-static',
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(nodes).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// some issue wiht the tempfs
|
||||||
|
describe('not root project', () => {
|
||||||
|
const tempFs = new TempFs('test');
|
||||||
|
beforeEach(() => {
|
||||||
|
context = {
|
||||||
|
nxJsonConfiguration: {
|
||||||
|
namedInputs: {
|
||||||
|
default: ['{projectRoot}/**/*'],
|
||||||
|
production: ['!{projectRoot}/**/*.spec.ts'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
workspaceRoot: tempFs.tempDir,
|
||||||
|
};
|
||||||
|
|
||||||
|
tempFs.createFileSync(
|
||||||
|
'my-app/project.json',
|
||||||
|
JSON.stringify({ name: 'my-app' })
|
||||||
|
);
|
||||||
|
tempFs.createFileSync('my-app/vite.config.ts', '');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create nodes', async () => {
|
||||||
|
const nodes = await createNodesFunction(
|
||||||
|
'my-app/vite.config.ts',
|
||||||
|
{
|
||||||
|
buildTargetName: 'build-something',
|
||||||
|
serveTargetName: 'my-serve',
|
||||||
|
previewTargetName: 'preview-site',
|
||||||
|
testTargetName: 'vitest',
|
||||||
|
serveStaticTargetName: 'serve-static',
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(nodes).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
296
packages/vite/src/plugins/plugin.ts
Normal file
296
packages/vite/src/plugins/plugin.ts
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
import {
|
||||||
|
CreateDependencies,
|
||||||
|
CreateNodes,
|
||||||
|
CreateNodesContext,
|
||||||
|
TargetConfiguration,
|
||||||
|
detectPackageManager,
|
||||||
|
joinPathFragments,
|
||||||
|
readJsonFile,
|
||||||
|
workspaceRoot,
|
||||||
|
writeJsonFile,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { dirname, isAbsolute, join, relative, resolve } from 'path';
|
||||||
|
|
||||||
|
import { readTargetDefaultsForTarget } from 'nx/src/project-graph/utils/project-configuration-utils';
|
||||||
|
import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
|
||||||
|
import { UserConfig, loadConfigFromFile } from 'vite';
|
||||||
|
import { existsSync, readdirSync } from 'fs';
|
||||||
|
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
|
||||||
|
import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';
|
||||||
|
import { getLockFileName } from '@nx/js';
|
||||||
|
export interface VitePluginOptions {
|
||||||
|
buildTargetName?: string;
|
||||||
|
testTargetName?: string;
|
||||||
|
serveTargetName?: string;
|
||||||
|
previewTargetName?: string;
|
||||||
|
serveStaticTargetName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cachePath = join(projectGraphCacheDirectory, 'vite.hash');
|
||||||
|
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};
|
||||||
|
|
||||||
|
const calculatedTargets: Record<
|
||||||
|
string,
|
||||||
|
Record<string, TargetConfiguration>
|
||||||
|
> = {};
|
||||||
|
|
||||||
|
function readTargetsCache(): Record<
|
||||||
|
string,
|
||||||
|
Record<string, TargetConfiguration>
|
||||||
|
> {
|
||||||
|
return readJsonFile(cachePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeTargetsToCache(
|
||||||
|
targets: Record<string, Record<string, TargetConfiguration>>
|
||||||
|
) {
|
||||||
|
writeJsonFile(cachePath, targets);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createDependencies: CreateDependencies = () => {
|
||||||
|
writeTargetsToCache(calculatedTargets);
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createNodes: CreateNodes<VitePluginOptions> = [
|
||||||
|
'**/vite.config.{js,ts}',
|
||||||
|
async (configFilePath, options, context) => {
|
||||||
|
const projectRoot = dirname(configFilePath);
|
||||||
|
// Do not create a project if package.json and project.json isn't there.
|
||||||
|
const siblingFiles = readdirSync(join(context.workspaceRoot, projectRoot));
|
||||||
|
if (
|
||||||
|
!siblingFiles.includes('package.json') &&
|
||||||
|
!siblingFiles.includes('project.json')
|
||||||
|
) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
options = normalizeOptions(options);
|
||||||
|
|
||||||
|
const hash = calculateHashForCreateNodes(projectRoot, options, context, [
|
||||||
|
getLockFileName(detectPackageManager(context.workspaceRoot)),
|
||||||
|
]);
|
||||||
|
const targets = targetsCache[hash]
|
||||||
|
? targetsCache[hash]
|
||||||
|
: await buildViteTargets(configFilePath, projectRoot, options, context);
|
||||||
|
|
||||||
|
calculatedTargets[hash] = targets;
|
||||||
|
|
||||||
|
return {
|
||||||
|
projects: {
|
||||||
|
[projectRoot]: {
|
||||||
|
root: projectRoot,
|
||||||
|
targets,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
async function buildViteTargets(
|
||||||
|
configFilePath: string,
|
||||||
|
projectRoot: string,
|
||||||
|
options: VitePluginOptions,
|
||||||
|
context: CreateNodesContext
|
||||||
|
) {
|
||||||
|
const viteConfig = await loadConfigFromFile(
|
||||||
|
{
|
||||||
|
command: 'build',
|
||||||
|
mode: 'production',
|
||||||
|
},
|
||||||
|
configFilePath
|
||||||
|
);
|
||||||
|
|
||||||
|
const { buildOutputs, testOutputs } = getOutputs(
|
||||||
|
projectRoot,
|
||||||
|
viteConfig?.config
|
||||||
|
);
|
||||||
|
|
||||||
|
const namedInputs = getNamedInputs(projectRoot, context);
|
||||||
|
|
||||||
|
const targets: Record<string, TargetConfiguration> = {};
|
||||||
|
|
||||||
|
targets[options.buildTargetName] = await buildTarget(
|
||||||
|
context,
|
||||||
|
namedInputs,
|
||||||
|
buildOutputs,
|
||||||
|
options,
|
||||||
|
projectRoot
|
||||||
|
);
|
||||||
|
|
||||||
|
targets[options.serveTargetName] = serveTarget(projectRoot);
|
||||||
|
|
||||||
|
targets[options.previewTargetName] = previewTarget(projectRoot);
|
||||||
|
|
||||||
|
targets[options.testTargetName] = await testTarget(
|
||||||
|
context,
|
||||||
|
namedInputs,
|
||||||
|
testOutputs,
|
||||||
|
options,
|
||||||
|
projectRoot
|
||||||
|
);
|
||||||
|
|
||||||
|
targets[options.serveStaticTargetName] = serveStaticTarget(options) as {};
|
||||||
|
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function buildTarget(
|
||||||
|
context: CreateNodesContext,
|
||||||
|
namedInputs: {
|
||||||
|
[inputName: string]: any[];
|
||||||
|
},
|
||||||
|
outputs: string[],
|
||||||
|
options: VitePluginOptions,
|
||||||
|
projectRoot: string
|
||||||
|
) {
|
||||||
|
const targetDefaults = readTargetDefaultsForTarget(
|
||||||
|
options.buildTargetName,
|
||||||
|
context.nxJsonConfiguration.targetDefaults
|
||||||
|
);
|
||||||
|
|
||||||
|
const targetConfig: TargetConfiguration = {
|
||||||
|
command: `vite build`,
|
||||||
|
options: {
|
||||||
|
cwd: joinPathFragments(projectRoot),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (targetDefaults?.outputs === undefined) {
|
||||||
|
targetConfig.outputs = outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetDefaults?.cache === undefined) {
|
||||||
|
targetConfig.cache = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetDefaults?.inputs === undefined) {
|
||||||
|
targetConfig.inputs = [
|
||||||
|
...('production' in namedInputs
|
||||||
|
? ['production', '^production']
|
||||||
|
: ['default', '^default']),
|
||||||
|
{
|
||||||
|
externalDependencies: ['vite'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
function serveTarget(projectRoot: string) {
|
||||||
|
const targetConfig: TargetConfiguration = {
|
||||||
|
command: `vite serve`,
|
||||||
|
options: {
|
||||||
|
cwd: joinPathFragments(projectRoot),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return targetConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
function previewTarget(projectRoot: string) {
|
||||||
|
const targetConfig: TargetConfiguration = {
|
||||||
|
command: `vite preview`,
|
||||||
|
options: {
|
||||||
|
cwd: joinPathFragments(projectRoot),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return targetConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testTarget(
|
||||||
|
context: CreateNodesContext,
|
||||||
|
namedInputs: {
|
||||||
|
[inputName: string]: any[];
|
||||||
|
},
|
||||||
|
outputs: string[],
|
||||||
|
options: VitePluginOptions,
|
||||||
|
projectRoot: string
|
||||||
|
) {
|
||||||
|
const targetDefaults = readTargetDefaultsForTarget(
|
||||||
|
options.testTargetName,
|
||||||
|
context.nxJsonConfiguration.targetDefaults
|
||||||
|
);
|
||||||
|
|
||||||
|
const targetConfig: TargetConfiguration = {
|
||||||
|
command: `vitest run`,
|
||||||
|
options: {
|
||||||
|
cwd: joinPathFragments(projectRoot),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (targetDefaults?.outputs === undefined) {
|
||||||
|
targetConfig.outputs = outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetDefaults?.cache === undefined) {
|
||||||
|
targetConfig.cache = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetDefaults?.inputs === undefined) {
|
||||||
|
targetConfig.inputs = [
|
||||||
|
...('production' in namedInputs
|
||||||
|
? ['production', '^production']
|
||||||
|
: ['default', '^default']),
|
||||||
|
{
|
||||||
|
externalDependencies: ['vitest'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return targetConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
function serveStaticTarget(options: VitePluginOptions) {
|
||||||
|
const targetConfig: TargetConfiguration = {
|
||||||
|
executor: '@nx/web:file-server',
|
||||||
|
options: {
|
||||||
|
buildTarget: `${options.buildTargetName}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return targetConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOutputs(
|
||||||
|
projectRoot: string,
|
||||||
|
viteConfig: UserConfig
|
||||||
|
): {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test?.coverage?.reportsDirectory) {
|
||||||
|
testOutputs.push(getOutput(test.coverage.reportsDirectory, projectRoot));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { buildOutputs, testOutputs };
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeOptions(options: VitePluginOptions): VitePluginOptions {
|
||||||
|
options ??= {};
|
||||||
|
options.buildTargetName ??= 'build';
|
||||||
|
options.serveTargetName ??= 'serve';
|
||||||
|
options.previewTargetName ??= 'preview';
|
||||||
|
options.testTargetName ??= 'test';
|
||||||
|
options.serveStaticTargetName ??= 'serve-static';
|
||||||
|
return options;
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import {
|
|||||||
ensurePackage,
|
ensurePackage,
|
||||||
getPackageManagerCommand,
|
getPackageManagerCommand,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
|
readNxJson,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { webStaticServeGenerator } from '@nx/web';
|
import { webStaticServeGenerator } from '@nx/web';
|
||||||
|
|
||||||
@ -16,10 +17,18 @@ export async function addE2e(
|
|||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
switch (options.e2eTestRunner) {
|
switch (options.e2eTestRunner) {
|
||||||
case 'cypress': {
|
case 'cypress': {
|
||||||
webStaticServeGenerator(tree, {
|
const nxJson = readNxJson(tree);
|
||||||
buildTarget: `${options.projectName}:build`,
|
const hasPlugin = nxJson.plugins?.some((p) =>
|
||||||
targetName: 'serve-static',
|
typeof p === 'string'
|
||||||
});
|
? p === '@nx/vite/plugin'
|
||||||
|
: p.plugin === '@nx/vite/plugin'
|
||||||
|
);
|
||||||
|
if (!hasPlugin) {
|
||||||
|
webStaticServeGenerator(tree, {
|
||||||
|
buildTarget: `${options.projectName}:build`,
|
||||||
|
targetName: 'serve-static',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const { configurationGenerator } = ensurePackage<
|
const { configurationGenerator } = ensurePackage<
|
||||||
typeof import('@nx/cypress')
|
typeof import('@nx/cypress')
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
||||||
import {
|
import {
|
||||||
|
getProjects,
|
||||||
readNxJson,
|
readNxJson,
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
Tree,
|
Tree,
|
||||||
@ -28,6 +29,7 @@ describe('web app generator (PCv3)', () => {
|
|||||||
const nxJson = readNxJson(tree);
|
const nxJson = readNxJson(tree);
|
||||||
nxJson.plugins ??= [];
|
nxJson.plugins ??= [];
|
||||||
nxJson.plugins.push('@nx/webpack/plugin');
|
nxJson.plugins.push('@nx/webpack/plugin');
|
||||||
|
nxJson.plugins.push('@nx/vite/plugin');
|
||||||
updateNxJson(tree, nxJson);
|
updateNxJson(tree, nxJson);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -50,4 +52,16 @@ describe('web app generator (PCv3)', () => {
|
|||||||
`assets: ['./src/favicon.ico', './src/assets']`
|
`assets: ['./src/favicon.ico', './src/assets']`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not add targets for vite', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
name: 'my-vite-app',
|
||||||
|
bundler: 'vite',
|
||||||
|
});
|
||||||
|
const projects = getProjects(tree);
|
||||||
|
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();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -16,7 +16,6 @@ import {
|
|||||||
workspaceRoot,
|
workspaceRoot,
|
||||||
logger,
|
logger,
|
||||||
readJsonFile,
|
readJsonFile,
|
||||||
ProjectGraphProjectNode,
|
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { existsSync } from 'fs';
|
import { existsSync } from 'fs';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user