From 73f5ee9434f52b307ce784fa071e7c340e186c91 Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Thu, 5 Nov 2020 08:40:56 -0500 Subject: [PATCH] docs(node): add node documentation for workspace configuration --- docs/node/guides/configuration.md | 370 ++++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 docs/node/guides/configuration.md diff --git a/docs/node/guides/configuration.md b/docs/node/guides/configuration.md new file mode 100644 index 0000000000000..4b44b8039c827 --- /dev/null +++ b/docs/node/guides/configuration.md @@ -0,0 +1,370 @@ +# Configuration + +There are three top-level configuration files every Nx workspace has: `workspace.json`, `nx.json`, and `tsconfig.json`. Many Nx plugins will modify these files when generating new code, but you can also modify them manually. + +## workspace.json + +The `workspace.json` configuration file contains information about the targets and schematics. Let's look at the following example: + +```json +{ + "projects": { + "myapp": { + "root": "apps/myapp/", + "sourceRoot": "apps/myapp/src", + "projectType": "application", + "architect": { + "build": { + "builder": "@nrwl/node:build", + "outputs": ["dist/apps/myapp"], + "options": { + "outputPath": "dist/packages/myapp", + "main": "packages/myapp/src/main.ts", + "tsConfig": "packages/myapp/tsconfig.app.json", + "assets": ["packages/myapp/src/assets"] + }, + "configurations": { + "production": { + "optimization": true + } + } + }, + "serve": { + "builder": "@nrwl/node:execute", + "options": { + "buildTarget": "myapp:build" + } + }, + "test": { + "builder": "@nrwl/jest:jest", + "options": { + "jestConfig": "apps/myapp/jest.config.js" + } + } + } + }, + "mylib": { + "root": "libs/mylib/", + "sourceRoot": "libs/mylib/src", + "projectType": "library", + "architect": { + "test": { + "builder": "@nrwl/jest:jest", + "options": { + "jestConfig": "libs/mylib/jest.config.js", + "tsConfig": "libs/mylib/tsconfig.spec.json" + } + }, + "build": { + "builder": "@nrwl/node:package", + "options": { + "outputPath": "dist/libs/mylib", + "tsConfig": "libs/mylib/tsconfig.lib.json", + "packageJson": "libs/mylib/package.json", + "main": "libs/mylib/src/index.ts", + "assets": ["libs/mylib/*.md"] + } + } + } + } + }, + "cli": { + "defaultCollection": "@nrwl/node" + }, + "schematics": { + "@nrwl/node:library": { + "js": true + } + } +} +``` + +### Projects + +The `projects` property configures all apps and libs. + +For instance, the following configures `mylib`. + +```json +{ + "mylib": { + "root": "libs/mylib/", + "sourceRoot": "libs/mylib/src", + "projectType": "library", + "architect": {} + } +} +``` + +- `root` tells Nx the location of the library including its sources and configuration files. +- `sourceRoot` tells Nx the location of the library's source files. +- `projectType` is either 'application' or 'library'. +- `architect` configures all the targets which define what tasks you can run against the library. + +> Nx uses the architect library built by the Angular team at Google. The naming reflects that. Important to note: it's a general purpose library that **does not** have any dependency on Angular. + +### Targets + +Let's look at the simple architect target: + +```json +{ + "test": { + "builder": "@nrwl/jest:jest", + "options": { + "jestConfig": "libs/mylib/jest.config.js" + } + } +} +``` + +**Target Name** + +The name of the target `test` means that you can invoke it as follows: `nx test mylib` or `nx run mylib:test`. The name isn't significant in any other way. If you rename it to, for example, `mytest`, you will be able to run as follows: `nx run mylib:mytest`. + +**Builder** + +The `builder` property tells Nx what function to invoke when you run the target. `"@nrwl/jest:jest"` tells Nx to find the `@nrwl/jest` package, find the builder named `jest` and invoke it with the options. + +**Options** + +The `options` provides a map of values that will be passed to the builder. The provided command line args will be merged into this map. I.e., `nx test mylib --jestConfig=libs/mylib/another-jest.config.js` will pass the following to the builder: + +```json +{ + "jestConfig": "libs/mylib/another-jest.config.js" +} +``` + +**Outputs** + +The `outputs` property lists the folders the builder will create files in. The property is optional. If not provided, Nx will assume it is `dist/libs/mylib`. + +```json +{ + "build": { + "builder": "@nrwl/node:package", + "options": { + "outputPath": "dist/libs/mylib", + "tsConfig": "libs/mylib/tsconfig.lib.json", + "packageJson": "libs/mylib/package.json", + "main": "libs/mylib/src/index.ts", + "assets": ["libs/mylib/*.md"] + } + } +} +``` + +**Configurations** + +The `configurations` property provides extra sets of values that will be merged into the options map. + +```json +{ + "build": { + "builder": "@nrwl/node:package", + "options": { + "outputPath": "dist/libs/mylib", + "tsConfig": "libs/mylib/tsconfig.lib.json", + "packageJson": "libs/mylib/package.json", + "main": "libs/mylib/src/index.ts", + "assets": ["libs/mylib/*.md"] + } + }, + "configurations": { + "production": { + "packageJson": "libs/mylib/package.prod.json" + } + } +} +``` + +You can select a configuration like this: `nx build mylib --configuration=production` or `nx run mylib:build:configuration=production`. + +The following show how the builder options get constructed: + +```bash +require(`@nrwl/jest`).builders['jest']({...options, ...selectedConfiguration, ...commandLineArgs}}) // Pseudocode +``` + +The selected configuration adds/overrides the default options, and the provided command line args add/override the configuration options. + +### Schematics + +You can configure default schematic options in `workspace.json` as well. For instance, the following will tell Nx to always pass `--js` when creating new libraries. + +```json +{ + "schematics": { + "@nrwl/node:library": { + "buildable": true + } + } +} +``` + +You can also do it on the project level: + +```json +{ + "mylib": { + "root": "libs/mylib/", + "sourceRoot": "libs/mylib/src", + "projectType": "library", + "schematics": { + "@nrwl/node:lib": { + "moreOptions": true + } + }, + "architect": {} + } +} +``` + +### CLI Options + +The following command will generate a new library: `nx g @nrwl/node:lib mylib`. If you set the `defaultCollection` property, you can generate the lib without mentioning the collection name: `nx g lib mylib`. + +```json +{ + "cli": { + "defaultCollection": "@nrwl/node" + } +} +``` + +## nx.json + +The `nx.json` file contains extra configuration options mostly related to the project graph. + +```json +{ + "npmScope": "happyorg", + "affected": { + "defaultBase": "master" + }, + "tasksRunnerOptions": { + "default": { + "runner": "@nrwl/workspace/tasks-runners/default", + "options": { + "cacheableOperations": ["build", "lint", "test", "e2e"] + } + } + }, + "implicitDependencies": { + "workspace.json": "*", + "package.json": { + "dependencies": "*", + "devDependencies": "*" + }, + "tsconfig.json": "*", + "nx.json": "*" + }, + "projects": { + "myapp": { + "tags": [] + }, + "mylib": { + "tags": [] + }, + "myapp-e2e": { + "tags": [], + "implicitDependencies": ["myapp"] + } + } +} +``` + +**NPM Scope** + +Tells Nx what prefix to use when generating library imports. + +**Affected** + +Tells Nx which branch and HEAD to use when calculating affected projects. + +- `defaultBase` defines the default base branch, defaulted to `master`. + +### Tasks Runner Options + +Tasks runners are invoked when you run `nx test`, `nx build`, `nx run-many`, `nx affected`, etc.. The tasks runner named "default" will be, unsurprisingly, used by default. But you can specify a different one by passing `--runner`. + +> A task is an invocation of a target. + +Tasks runners can accept different options. The following are the options supported by `"@nrwl/workspace/tasks-runners/default"` and `"@nrwl/nx-cloud"`. + +- `cacheableOperations` defines the list of targets/operations that will be cached by Nx. +- `strictlyOrderedTargets` defines the list of targets that need to be executed in the order defined by the dependency graph. Defaults to `['build']` +- `parallel` defines whether to run targets in parallel +- `maxParallel` defines the max number of processes used. +- `captureStderr` defines whether the cache will capture stderr or just stdout +- `skipNxCache` defines whether the Nx Cache should be skipped. Defaults to `false` +- `cacheDirectory` defines where the local cache is stored, which is `node_modules/.cache/nx` by default. +- `encryptionKey` (when using `"@nrwl/nx-cloud"` only) defines an encryption key to support end-to-end encryption of your cloud cache. You may also provide an environment variable with the key `NX_CLOUD_ENCRYPTION_KEY` that contains an encryption key as its value. The Nx Cloud task runner will normalize the key length, so any length of key is acceptable. +- `runtimeCacheInputs` defines the list of commands that will be run by the runner to include into the computation hash value. + +`runtimeCacheInputs` can be set as follows: + +```json +{ + "tasksRunnerOptions": { + "default": { + "runner": "@nrwl/workspace/tasks-runners/default", + "options": { + "cacheableOperations": ["build", "lint", "test", "e2e"], + "runtimeCacheInputs": ["node -v"] + } + } + } +} +``` + +You can configure `parallel` and `maxParallel` in `nx.json`, but you can also pass them in the terminal `nx run-many --target=test --parallel`. + +### Implicit Dependencies + +Nx performs advanced source-code analysis to figure out the project graph of the workspace. So when you make a change, Nx can deduce what can be broken by this change. Some dependencies between projects and dependencies between shared files and projects cannot be inferred statically. You can configure those using `implicitDependencies`. + +```json +{ + "implicitDependencies": { + "workspace.json": "*", + "package.json": { + "dependencies": "*", + "devDependencies": { + "mypackage": ["mylib"] + }, + "scripts": { + "check:*": "*" + } + }, + "globalFile": ["myapp"], + "styles/**/*.css": ["myapp"] + } +} +``` + +In the example above: + +- Changing `workspace.json` will affect every project. +- Changing the `dependencies` property in `package.json` will affect every project. +- Changing the `devDependencies` property in `package.json` will only affect `mylib`. +- Changing any of the custom check `scripts` in `package.json` will affect every project. +- Changing `globalFile` will only affect `myapp`. +- Changing any CSS file inside the `styles` directory will only affect `myapp`. + +You can also add dependencies between projects. For instance, the example below defines a dependency from `myapp-e2e` to `myapp`, such that every time `myapp` is affected, `myapp-e2e` is affected as well. + +```json +{ + "projects": { + "myapp": { + "tags": [] + }, + "myapp-e2e": { + "tags": [], + "implicitDependencies": ["myapp"] + } + } +} +```