diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 9ce8b5eedb..9df4922abf 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -1177,6 +1177,14 @@ "isExternal": false, "children": [], "disableCollapsible": false + }, + { + "name": "Migrate to Inferred Tasks (Project Crystal)", + "path": "/recipes/running-tasks/convert-to-inferred", + "id": "convert-to-inferred", + "isExternal": false, + "children": [], + "disableCollapsible": false } ], "disableCollapsible": false @@ -2175,6 +2183,14 @@ "isExternal": false, "children": [], "disableCollapsible": false + }, + { + "name": "Migrate to Inferred Tasks (Project Crystal)", + "path": "/recipes/running-tasks/convert-to-inferred", + "id": "convert-to-inferred", + "isExternal": false, + "children": [], + "disableCollapsible": false } ], "disableCollapsible": false @@ -2267,6 +2283,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Migrate to Inferred Tasks (Project Crystal)", + "path": "/recipes/running-tasks/convert-to-inferred", + "id": "convert-to-inferred", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Adopting Nx", "path": "/recipes/adopting-nx", diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index d1ddfa1a57..0ee24e81d2 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -1608,6 +1608,17 @@ "isExternal": false, "path": "/recipes/running-tasks/skipping-cache", "tags": [] + }, + { + "id": "convert-to-inferred", + "name": "Migrate to Inferred Tasks (Project Crystal)", + "description": "", + "mediaImage": "", + "file": "shared/recipes/running-tasks/convert-to-inferred", + "itemList": [], + "isExternal": false, + "path": "/recipes/running-tasks/convert-to-inferred", + "tags": ["inferred-tasks", "automate-updating-dependencies"] } ], "isExternal": false, @@ -2974,6 +2985,17 @@ "isExternal": false, "path": "/recipes/running-tasks/skipping-cache", "tags": [] + }, + { + "id": "convert-to-inferred", + "name": "Migrate to Inferred Tasks (Project Crystal)", + "description": "", + "mediaImage": "", + "file": "shared/recipes/running-tasks/convert-to-inferred", + "itemList": [], + "isExternal": false, + "path": "/recipes/running-tasks/convert-to-inferred", + "tags": ["inferred-tasks", "automate-updating-dependencies"] } ], "isExternal": false, @@ -3101,6 +3123,17 @@ "path": "/recipes/running-tasks/skipping-cache", "tags": [] }, + "/recipes/running-tasks/convert-to-inferred": { + "id": "convert-to-inferred", + "name": "Migrate to Inferred Tasks (Project Crystal)", + "description": "", + "mediaImage": "", + "file": "shared/recipes/running-tasks/convert-to-inferred", + "itemList": [], + "isExternal": false, + "path": "/recipes/running-tasks/convert-to-inferred", + "tags": ["inferred-tasks", "automate-updating-dependencies"] + }, "/recipes/adopting-nx": { "id": "adopting-nx", "name": "Adopting Nx", diff --git a/docs/generated/manifests/tags.json b/docs/generated/manifests/tags.json index 9a6cef3ba6..69a6bf6340 100644 --- a/docs/generated/manifests/tags.json +++ b/docs/generated/manifests/tags.json @@ -353,6 +353,13 @@ "name": "Automate Updating Dependencies", "path": "/features/automate-updating-dependencies" }, + { + "description": "", + "file": "shared/recipes/running-tasks/convert-to-inferred", + "id": "convert-to-inferred", + "name": "Migrate to Inferred Tasks (Project Crystal)", + "path": "/recipes/running-tasks/convert-to-inferred" + }, { "description": "", "file": "shared/recipes/tips-n-tricks/keep-nx-versions-in-sync", @@ -585,6 +592,13 @@ "name": "Inferred Tasks", "path": "/concepts/inferred-tasks" }, + { + "description": "", + "file": "shared/recipes/running-tasks/convert-to-inferred", + "id": "convert-to-inferred", + "name": "Migrate to Inferred Tasks (Project Crystal)", + "path": "/recipes/running-tasks/convert-to-inferred" + }, { "description": "", "file": "shared/recipes/plugins/project-graph-plugins", diff --git a/docs/map.json b/docs/map.json index 0c78167556..a4b37f1603 100644 --- a/docs/map.json +++ b/docs/map.json @@ -431,6 +431,12 @@ "name": "Skip Task Caching", "id": "skipping-cache", "file": "shared/recipes/running-tasks/skipping-cache" + }, + { + "name": "Migrate to Inferred Tasks (Project Crystal)", + "id": "convert-to-inferred", + "tags": ["inferred-tasks", "automate-updating-dependencies"], + "file": "shared/recipes/running-tasks/convert-to-inferred" } ] }, diff --git a/docs/shared/concepts/inferred-tasks.md b/docs/shared/concepts/inferred-tasks.md index c6cdcd93ce..0d0cb4ebfe 100644 --- a/docs/shared/concepts/inferred-tasks.md +++ b/docs/shared/concepts/inferred-tasks.md @@ -74,15 +74,13 @@ More details about how to override task configuration is available in these reci ## Existing Nx Workspaces -If you have an existing Nx Workspace and upgrade to Nx 18, the migration generator will automatically add `NX_ADD_PLUGINS=false` to your `.env` file. This environment variable allows you to continue to use Nx without inferred tasks. Alternatively, you can set the `useInferencePlugins` property to `false` in `nx.json`. +If you have an existing Nx Workspace and upgrade to the latest Nx version, a migration will automatically set `useInferencePlugins` to `false` in `nx.json`. This property allows you to continue to use Nx without inferred tasks. -We are working on creating migrations for existing workspaces to start switching to inferred tasks, where desired. - -When `NX_ADD_PLUGINS` or `useInferencePlugins` is `false`: +When `useInferencePlugins` is `false`: 1. A newly generated project will have all targets defined with executors - not with inferred tasks. 2. Running `nx add @nx/some-plugin` will not create a plugin entry for `@nx/some-plugin` in the `nx.json` file. (So that plugin will not create inferred tasks.) -If your `.env` file is ignored by git, ensure that everyone in your organization sets `NX_ADD_PLUGINS=false`. This could be done by updating a shared `.env` file or setting the environment variable in everyone's `.bashrc` file. +If you want to **migrate** your projects to use inferred tasks, follow the recipe for [migrating to inferred tasks](/recipes/running-tasks/convert-to-inferred). Even once a repository has fully embraced inferred tasks, `project.json` and executors will still be useful. The `project.json` file is needed to modify inferred task options and to define tasks that can not be inferred. Some executors perform tasks that can not be accomplished by running a tool directly from the command line (i.e. [TypeScript batch mode](/recipes/tips-n-tricks/enable-tsc-batch-mode)). diff --git a/docs/shared/recipes/running-tasks/convert-to-inferred.md b/docs/shared/recipes/running-tasks/convert-to-inferred.md new file mode 100644 index 0000000000..28e92882ff --- /dev/null +++ b/docs/shared/recipes/running-tasks/convert-to-inferred.md @@ -0,0 +1,204 @@ +# Migrate to Inferred Tasks (Project Crystal) + +In this recipe, you'll learn how to migrate an existing Nx workspace from using executors in `project.json` to using [inferred tasks](/concepts/inferred-tasks). + +The main benefits of migrating to inferred tasks are + +- reducing the amount of configuration needed in `project.json` +- inferring the correct cache settings based on the tool configuration files +- [splitting tasks (Atomizer)](/ci/features/split-e2e-tasks) for plugins that support it + +{% youtube +src="https://youtu.be/wADNsVItnsM" +title="Project Crystal" +/%} + +For the best experience, we recommend that you [migrate](/features/automate-updating-dependencies) to the latest Nx version before continuing. At minimum, you should be on Nx version 19.6. + +```shell +npx nx migrate latest +``` + +## Migrate a Plugin + +Most of the official plugins come with a `convert-to-inferred` generator. This generator will + +- register the inference plugin in the `plugins` section of `nx.json` +- migrate executor options into the tool's configuration files (where applicable) +- clean up `project.json` to remove targets and options that are unnecessary + +To get started, run `nx g convert-to-inferred`, and you'll be prompted to choose a plugin to migrate. + +```text {% command="npx nx g convert-to-inferred" %} +? Which generator would you like to use? … +@nx/eslint:convert-to-inferred +@nx/playwright:convert-to-inferred +@nx/vite:convert-to-inferred + +None of the above +``` + +{% callout type="note" title="Third-party plugins" %} +For third-party plugins that provide `convert-to-inferred` generators, you should pick the `None of the above` option and type in the name of the package manually. Alternatively, you can also provide the package explicitly with `nx g :convert-to-inferred`. +{% /callout %} + +We recommend that you migrate the plugins one at a time, and check that the configurations are correct before continuing to the next plugin. If you only want to try it on a single project, pass the `--project` option. + +## Understand the Migration Process + +The `convert-to-inferred` generator removes uses of executors from the corresponding plugin. For example, if `@nx/vite` is migrated, then uses of [`@nx/vite:build`](/nx-api/vite/executors/build), [`@nx/vite:dev-server`](/nx-api/vite/executors/dev-server), [`@nx/vite:preview-server`](/nx-api/vite/executors/preview-server), and [`@nx/vite:test`](/nx-api/vite/executors/test) executors will be removed. + +Target and configuration names are maintained for each project in their `project.json` files. A target may be removed from `project.json` if everything is inferred--that is, options and configurations are not customized. To get the full project details (including all inferred tasks), run: + +```shell +npx nx show project +``` + +For example, if we migrated the `@nx/vite` plugin for a single app (i.e. `nx g @nx/vite:convert-to-inferred --project demo`), then running `nx show project demo` will show a screen similar to the following. + +{% project-details title="Test" height="100px" %} + +```json +{ + "project": { + "name": "demo", + "data": { + "root": " apps/demo", + "projectType": "application", + "targets": { + "serve": { + "executor": "nx:run-commands", + "options": { + "command": "vite dev" + } + }, + "build": { + "executor": "nx:run-commands", + "inputs": ["production", "^production"], + "outputs": ["{projectRoot}/dist"], + "options": { + "command": "vite build" + } + } + } + } + }, + "sourceMap": { + "targets": ["apps/demo/vite.config.ts", "@nx/vite"], + "targets.serve": ["apps/demo/vite.config.ts", "@nx/vite"], + "targets.build": ["apps/demo/vite.config.ts", "@nx/vite"] + } +} +``` + +{% /project-details %} + +You'll notice that the `serve` and `build` tasks are running the [Vite CLI](https://vitejs.dev/guide/cli.html) and there are no references to Nx executors. Since the targets directly invoke the Vite CLI, any options that may be passed to it can be passed via Nx commands. e.g. `nx serve demo --cors --port 8888` enables CORs and uses port `8888` using [Vite CLI options](https://vitejs.dev/guide/cli.html#options) +The same CLI setup applies to other plugins as well. + +- `@nx/cypess` calls the [Cypress CLI](https://docs.cypress.io/guides/guides/command-line) +- `@nx/playwright` calls the [Playwright CLI](https://playwright.dev/docs/test-cli) +- `@nx/webpack` calls the [Webpack CLI](https://webpack.js.org/api/cli/) +- etc. + +Read the recipe on [passing args to commands](/recipes/running-tasks/pass-args-to-commands) for more information. + +### Configuration File Changes + +There may also be changes to the configuration files used by the underlying tool. The changes come with comments to explain them, and may also provide next steps for you to take. One common change is to add support for different configuration options. For example, if we have an existing Vite app with the following build target: + +```json {% fileName="project.json" %} +"build": { + "executor": "@nx/vite:build", + "options": { + "mode": "development" + }, + "defaultConfiguration": "production", + "configurations": { + "development": {}, + "production": {}, + "ci": {} + } +} +``` + +Where we have `development`, `production`, and `ci` configurations. Then running `nx g @nx/vite:convert-to-inferred` will result in these lines added to `vite.config.ts`. + +```ts {% fileName="vite.config.ts" highlightLines=["6-15"] %} +/// +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +// These options were migrated by @nx/vite:convert-to-inferred from the project.json file. +const configValues = { default: {}, development: {}, production: {}, ci: {} }; + +// Determine the correct configValue to use based on the configuration +const nxConfiguration = process.env.NX_TASK_TARGET_CONFIGURATION ?? 'default'; + +const options = { + ...configValues.default, + ...(configValues[nxConfiguration] ?? {}), +}; + +export default defineConfig({ + root: __dirname, + cacheDir: '../../node_modules/.vite/apps/demo', + // ... +}); +``` + +The configuration changes ensure that passing `--configuration` still work for the target. Differences in options can be added to the `configValues` object, and the right value is determined using the `NX_TASK_TARGET_CONFIGURATION` [environment variable](/reference/environment-variables). Again, there may be other types of changes so read the comments to understand them. + +### Register the Plugin with Nx + +Lastly, you can inspect the `nx.json` file to see a new `plugins` entry. For `@nx/vite`, there should be an entry like this: + +```json {% fileName="nx.json" %} +{ + "plugin": "@nx/vite/plugin", + "options": { + "buildTargetName": "build", + "serveTargetName": "serve", + "previewTargetName": "preview", + "testTargetName": "test", + "serveStaticTargetName": "serve-static" + } +} +``` + +You may change the target name options to change how Nx adds them to the project. For example, if you use `"serveTargetName": "dev"` then you would run `nx dev demo` rather than `nx serve demo` for your Vite project. + +## Verify the Migration + +The migrations maintain the same targets and configurations for each project, thus to verify it you should run the affected targets. + +For example + +- for `@nx/vite` you should check the `build`, `serve`, and `test` targets +- for `@nx/playwright` you should check the `e2e` targets +- for `@nx/eslint` you should check the `lint` target +- etc. + +Remember that the target names are defined in the plugin configuration in `nx.json`. + +Make sure that the tasks are all passing before migrating another plugin. + +## Enable Atomizer (task splitting) + +These plugins come with the [Atomizer](/ci/features/split-e2e-tasks) feature. + +- `@nx/cypress` +- `@nx/jest` +- `@nx/gradle` +- `@nx/playwright` + +The Atomizer splits potentially slow tasks into separate tasks per file. This feature along with [task distribution](/ci/features/distribute-task-execution) can speed up CI by distributing the split tasks among many agents. + +To enable Atomizer, make sure that you are [connected to Nx Cloud](/ci/intro/connect-to-nx-cloud), and that you have distribution enabled in CI. Some plugins require extra configuration to enable Atomizer, so check the [individual plugin documentation page](/nx-api) for more details. + +{% call-to-action title="Connect to Nx Cloud" icon="nxcloud" description="Enable task distribution and Atomizer" url="/ci/intro/connect-to-nx-cloud" /%} + +## Troubleshooting + +If you run into any issues during the migration, refer to the [troubleshooting guide](/troubleshooting/convert-to-inferred). diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 961fcc0696..ca28f28fa9 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -64,6 +64,7 @@ - [Reduce Repetitive Configuration](/recipes/running-tasks/reduce-repetitive-configuration) - [Change Cache Location](/recipes/running-tasks/change-cache-location) - [Skip Task Caching](/recipes/running-tasks/skipping-cache) + - [Migrate to Inferred Tasks (Project Crystal)](/recipes/running-tasks/convert-to-inferred) - [Adopting Nx](/recipes/adopting-nx) - [NPM/Yarn/PNPM workspaces](/recipes/adopting-nx/adding-to-monorepo) - [Migrate From Turborepo](/recipes/adopting-nx/from-turborepo)