From 2177aae6eba87a3b8a504133efb7b9d0fef2efc5 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Mon, 18 Apr 2022 13:19:18 -0400 Subject: [PATCH] docs(nx-plugin): add documentation for project inference plugins (#9757) --- docs/map.json | 11 ++ .../extending-nx/project-inference-plugins.md | 100 ++++++++++++++++++ .../src/lib/menu.utils.ts | 1 + 3 files changed, 112 insertions(+) create mode 100644 docs/shared/extending-nx/project-inference-plugins.md diff --git a/docs/map.json b/docs/map.json index b13bb1f8df8a0..7e4abc1fdc991 100644 --- a/docs/map.json +++ b/docs/map.json @@ -106,6 +106,17 @@ } ] }, + { + "name": "Extending Nx", + "id": "extending-nx", + "itemList": [ + { + "name": "Project Inference Plugins", + "id": "project-inference-plugins", + "file": "shared/extending-nx/project-inference-plugins" + } + ] + }, { "name": "Migration", "id": "migration", diff --git a/docs/shared/extending-nx/project-inference-plugins.md b/docs/shared/extending-nx/project-inference-plugins.md new file mode 100644 index 0000000000000..6fb4899de658d --- /dev/null +++ b/docs/shared/extending-nx/project-inference-plugins.md @@ -0,0 +1,100 @@ +# Project Inference + +> This API is experimental and might change. + +Project inference describes the ability of Nx to discover and work with projects based on source code and configuration files in your repo. + +One of the best examples of this in Nx is that `package.json` scripts are automatically inferred as targets for your workspace. If using nx core, without `workspace.json`, `nx` can also infer projects defined in your `package.json` workspace are inferred as Nx projects. + +## Adding Plugins to Workspace + +You can register a plugin by adding it to the plugins array in `nx.json`: + +```json +{ + ..., + "plugins": [ + "awesome-plugin" + ] +} +``` + +## Project File Patterns + +Project file patterns are used in two scenarios: + +- Inferring projects when `workspace.json` is not present +- Determining which files should be passed into `registerProjectTargets`. + +Lets use the below plugin and workspace layout as an example: + +> libs/awesome-plugin/index.ts + +```typescript +export const projectFilePatterns = ['project.json', 'my-other-project-file']; +export function registerProjectTargets(projectFilePath) { + console.log(projectFilePath); +} +``` + +> workspace layout + +```text +my-workspace/ +├─ node_modules/ +├─ libs/ +│ ├─ my-project/ +│ │ ├─ my-other-project-file +│ ├─ nx-project/ +│ │ ├─ my-other-project-file +│ │ ├─ project.json +├─ nx.json +├─ package.json + +``` + +During initialization, we would expect to see "libs/my-project/my-other-project-file", "libs/nx-project/my-other-project-file", "libs/nx-project/project.json" all logged out to the console. Since `workspace.json` is not present, Nx was able to infer `my-project` from the layout. + +If `workspace.json` was present, `my-project` wouldn't be able to be inferred, since full project inference requires `workspace.json` to be absent. + +## Implementing a Project Target Configurator + +A project target configurator is a function that takes a path to a project file, and returns the targets inferred from that file. + +Plugins should export a function named `registerProjectTargets` that infers the targets from each matching project file. This function receives the path to the project file as its sole parameter. + +The `registerProjectTargets` function should return a `Record`, which describes the targets inferred for that specific project file. + +```typescript +import { + TargetConfiguration +} from '@nrwl/devkit'; + +export function registerProjectTargets( + projectFilePath: string +): Record { + return { + "build" { + /** + * This object should look exactly like a target + * configured inside `project.json` + */ + } + } +} +``` + +## Multiple Matches + +It is possible that the registerProjectTargets function may be called multiple times for one project. This could occur in a few cases, one of which is demonstrated above. + +- One plugin may list multiple file patterns, and a project may match more than one of them. +- Multiple plugins may list similar patterns, and pick up the project separately. + +In the first case, the plugin that you are writing will be called into multiple times. If you return the same target (e.g. `build`) on each call, whichever is ran last would be the target that Nx calls into. The order that the function would be called is **NOT** guaranteed, so you should try to avoid this when possible. If specifying multiple patterns, they should either be mutually exclusive (e.g. one match per project) or the plugin should conditionally add targets based on the file passed in. + +In the second case, different plugins may attempt to register the same target on a project. If this occurs, whichever target was registered by the plugin listed latest in `nx.json` would be the one called into by Nx. As an example, assume `plugin-a`, `plugin-b`, and `plugin-c` all match a file and register `build` as a target. If `nx.json` included `"plugins": ["plugin-a", "plugin-b", "plugin-c"]`, running `nx build my-project` would run the target as defined by `"plugin-c"`. Alternatively, if `nx.json` included `"plugins": ["plugin-c", "plugin-b", "plugin-a"]`, running `nx build my-project` would run the target as defined by `"plugin-a"` + +## Development Tips + +There is a cache that Nx uses to avoid recalculating the project graph as much as possible, but it may need to be skipped during plugin development. You can set the following environment variable to disable the project graph cache: `NX_CACHE_PROJECT_GRAPH=false`. It might also be a good idea to ensure that the dep graph is not running on the nx daemon by setting `NX_DAEMON=false`, as this will ensure you will be able to see any `console.log` statements you add as you're developing. You can also leave the daemon active, but `console.log` statements would only appear in its log file. diff --git a/nx-dev/data-access-documents/src/lib/menu.utils.ts b/nx-dev/data-access-documents/src/lib/menu.utils.ts index eafad5fcdf5f5..7f5d9d101e54d 100644 --- a/nx-dev/data-access-documents/src/lib/menu.utils.ts +++ b/nx-dev/data-access-documents/src/lib/menu.utils.ts @@ -65,6 +65,7 @@ export function getDeepDiveSection(items: MenuItem[]): MenuSection { (m) => m.id === 'workspace-concepts' || m.id === 'structure' || + m.id === 'extending-nx' || m.id === 'generators' || m.id === 'executors' || m.id === 'ci' ||