Skip to content

Commit

Permalink
feat(vite): allow user to set their custom target for transform
Browse files Browse the repository at this point in the history
  • Loading branch information
mandarini committed Dec 15, 2022
1 parent c3c9b2d commit 9b4fd95
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 13 deletions.
12 changes: 12 additions & 0 deletions docs/generated/packages/vite.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@
"description": "Is this a new project?",
"default": false,
"hidden": true
},
"buildTarget": {
"type": "string",
"description": "The build target of the project to be transformed to use the @nrwl/vite:build executor."
},
"serveTarget": {
"type": "string",
"description": "The serve target of the project to be transformed to use the @nrwl/vite:dev-server executor."
},
"testTarget": {
"type": "string",
"description": "The test target of the project to be transformed to use the @nrwl/vite:test executor."
}
},
"examplesFile": "This is a generator for setting up Vite configuration for an existing React or Web application. It will change the build and serve targets to use the `@nrwl/vite` executors for serving and building the application. This generator will modify your code, so make sure to commit your changes before running it.\n\n```bash\nnx g @nrwl/vite:configuration\n```\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `project`, as the name of the project you want to generate the configuration for.\n- The `uiFramework` you want to use. Supported values are: `react` and `none`.\n\nYou must provide a `project` and a `uiFramework` for the generator to work.\n\nYou can read more about how this generator works, in the [Vite package overview page](/packages/vite).\n\n## Examples\n\n### Change a React app to use Vite\n\n```bash\nnx g @nrwl/vite:configuration --project=my-app --uiFramework=react\n```\n\nThis will change the `my-app` project to use Vite instead of the default Webpack configuration. The changes this generator will do are described in the [Vite package overview page](/packages/vite).\n\n### Change a Web app to use Vite\n\n```bash\nnx g @nrwl/vite:configuration --project=my-app --uiFramework=none\n```\n\nThis will change the `my-app` project to use Vite instead of the existing bundler configuration.\n",
Expand Down
38 changes: 32 additions & 6 deletions packages/vite/src/generators/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
editTsConfig,
moveAndEditIndexHtml,
writeViteConfig,
handleUnsupportedCustomTargets,
} from '../../utils/generator-utils';

import initGenerator from '../init/init';
Expand All @@ -28,27 +29,52 @@ export async function viteConfigurationGenerator(tree: Tree, schema: Schema) {
);
let buildTargetName = 'build';
let serveTargetName = 'serve';
let testTargetName = 'test';

schema.includeLib ??= projectType === 'library';

if (!schema.newProject) {
const { buildTarget, serveTarget, unsuppored } =
findExistingTargets(targets);
const {
buildTarget,
serveTarget,
testTarget,
unsupported,
unsupportedCustomTarget,
} = findExistingTargets(targets, {
build: schema.buildTarget,
serve: schema.serveTarget,
test: schema.testTarget,
});

/**
* Here, we make sure that the project has a build target
* and it is unsupported, before throwing the error.
* Here, we make sure that the project has only
* unsupported build targets before throwing the error.
* The reason is that the project could not have a build
* target at all, in which case we don't want to throw.
* Or the project can have multiple build targets, one of which unsupported.
* Or the project can have multiple build targets,
* one of which unsupported.
* In that case, we convert the supported one.
*/
if (!buildTarget && unsuppored) {
if (!buildTarget && unsupported) {
throw new Error(
`The project ${schema.project} cannot be converted to use the @nrwl/vite executors.`
);
}

await handleUnsupportedCustomTargets(
unsupportedCustomTarget,
{
build: schema.buildTarget,
serve: schema.serveTarget,
test: schema.testTarget,
},
{
build: buildTargetName,
serve: serveTargetName,
test: testTarget,
}
);

buildTargetName = buildTarget ?? buildTargetName;
serveTargetName = serveTarget ?? serveTargetName;

Expand Down
3 changes: 3 additions & 0 deletions packages/vite/src/generators/configuration/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ export interface Schema {
includeVitest?: boolean;
inSourceTests?: boolean;
includeLib?: boolean;
buildTarget?: string;
serveTarget?: string;
testTarget?: string;
}
12 changes: 12 additions & 0 deletions packages/vite/src/generators/configuration/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@
"description": "Is this a new project?",
"default": false,
"hidden": true
},
"buildTarget": {
"type": "string",
"description": "The build target of the project to be transformed to use the @nrwl/vite:build executor."
},
"serveTarget": {
"type": "string",
"description": "The serve target of the project to be transformed to use the @nrwl/vite:dev-server executor."
},
"testTarget": {
"type": "string",
"description": "The test target of the project to be transformed to use the @nrwl/vite:test executor."
}
},
"examplesFile": "../../../docs/configuration-examples.md"
Expand Down
134 changes: 127 additions & 7 deletions packages/vite/src/utils/generator-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,33 @@ import { ViteDevServerExecutorOptions } from '../executors/dev-server/schema';
import { VitestExecutorOptions } from '../executors/test/schema';
import { Schema } from '../generators/configuration/schema';

export function findExistingTargets(targets: {
[targetName: string]: TargetConfiguration;
}): {
export function findExistingTargets(
targets: {
[targetName: string]: TargetConfiguration;
},
customTargets?: {
build?: string;
serve?: string;
test?: string;
}
): {
buildTarget?: string;
serveTarget?: string;
testTarget?: string;
unsuppored?: boolean;
unsupported?: boolean;
unsupportedCustomTarget?: {
build?: boolean;
serve?: boolean;
test?: boolean;
};
} {
let buildTarget, serveTarget, testTarget, unsuppored;
let buildTarget,
serveTarget,
testTarget,
unsupported,
unsupportedCustomTargetBuild,
unsupportedCustomTargetServe,
unsupportedCustomTargetTest;

const arrayOfBuilders = [
'@nxext/vite:build',
Expand Down Expand Up @@ -52,6 +70,30 @@ export function findExistingTargets(targets: {
'@nrwl/js:tsc',
];

if (customTargets.build) {
if (arrayOfBuilders.includes(targets[customTargets.build].executor)) {
buildTarget = customTargets.build;
} else {
unsupportedCustomTargetBuild = true;
}
}

if (customTargets.serve) {
if (arrayOfServers.includes(targets[customTargets.serve].executor)) {
buildTarget = customTargets.serve;
} else {
unsupportedCustomTargetServe = true;
}
}

if (customTargets.test) {
if (arrayOfServers.includes(targets[customTargets.test].executor)) {
buildTarget = customTargets.test;
} else {
unsupportedCustomTargetTest = true;
}
}

for (const target in targets) {
if (buildTarget && serveTarget && testTarget) {
break;
Expand All @@ -66,15 +108,20 @@ export function findExistingTargets(targets: {
testTarget = target;
}
if (arrayofUnsupported.includes(targets[target].executor)) {
unsuppored = true;
unsupported = true;
}
}

return {
buildTarget,
serveTarget,
testTarget,
unsuppored,
unsupported,
unsupportedCustomTarget: {
build: unsupportedCustomTargetBuild,
serve: unsupportedCustomTargetServe,
test: unsupportedCustomTargetTest,
},
};
}

Expand Down Expand Up @@ -497,3 +544,76 @@ export function getViteConfigPathForProject(

return normalizeViteConfigFilePathWithTree(tree, root, viteConfigPath);
}

export async function handleUnsupportedCustomTargets(
unsupportedCustomTarget?: {
build?: boolean;
serve?: boolean;
test?: boolean;
},
customTargets?: {
build: string;
serve: string;
test: string;
},
targets?: {
build: string;
serve: string;
test: string;
}
) {
if (unsupportedCustomTarget.build && targets.build) {
await handleUnsupportedCustomTargetsErrors(
customTargets.build,
targets.build,
'build',
'build'
);
}

if (unsupportedCustomTarget.serve && targets.serve) {
await handleUnsupportedCustomTargetsErrors(
customTargets.serve,
targets.serve,
'serve',
'dev-server'
);
}

if (unsupportedCustomTarget.test && targets.test) {
await handleUnsupportedCustomTargetsErrors(
customTargets.test,
targets.test,
'test',
'test'
);
}
}

export async function handleUnsupportedCustomTargetsErrors(
customTarget: string,
foundTarget: string,
action: 'build' | 'serve' | 'test',
executor: 'build' | 'dev-server' | 'test'
) {
logger.warn(
`The custom ${action} target you provided (${customTarget}) cannot be converted to use the @nrwl/vite:${executor} executor.
However, we found the following ${action} target in your project that can be converted: ${foundTarget}
`
);
const { Confirm } = require('enquirer');
const prompt = new Confirm({
name: 'question',
message: `Should we convert this target to use the @nrwl/vite:${executor} executor?`,
initial: true,
});
const shouldConvert = await prompt.run();
if (!shouldConvert) {
throw new Error(
`The ${action} target ${customTarget} cannot be converted to use the @nrwl/vite:${executor} executor.
Please try again, either by providing a different ${action} target or by not providing a target at all (Nx will
convert the first one it finds, most probably this one: ${foundTarget})
`
);
}
}

0 comments on commit 9b4fd95

Please sign in to comment.