Project Configuration

Projects can be configured in package.json (if you use npm scripts and not Nx executors) and project.json (if you use task executors). Both package.json and project.json files are located in each project's folder. Nx merges the two files to get each project's configuration. The full machine readable schema is available on GitHub.

The following configuration creates build and test targets for Nx.

package.json
1{ 2 "name": "mylib", 3 "scripts": { 4 "test": "jest", 5 "build": "tsc -p tsconfig.lib.json" // the actual command here is arbitrary 6 } 7} 8

You can invoke nx build mylib or nx test mylib without any extra configuration.

Below are some more complete examples of project configuration files. For a more intuitive understanding of the roles of each option, you can highlight the options in the excerpt below that relate to different categories.

package.json
1{ 2 "name": "mylib", 3 "scripts": { 4 "test": "jest", 5 "build": "tsc -p tsconfig.lib.json", // the actual command here is arbitrary 6 "ignored": "exit 1" 7 }, 8 "nx": { 9 "namedInputs": { 10 "default": ["{projectRoot}/**/*"], 11 "production": ["!{projectRoot}/**/*.spec.tsx"] 12 }, 13 "targets": { 14 "build": { 15 "inputs": ["production", "^production"], 16 "outputs": ["{workspaceRoot}/dist/libs/mylib"], 17 "dependsOn": ["^build"] 18 }, 19 "test": { 20 "inputs": ["default", "^production"], 21 "outputs": [], 22 "dependsOn": ["build"] 23 } 24 }, 25 "includedScripts": ["test", "build"] // If you want to limit the scripts Nx sees, you can specify a list here. 26 } 27} 28

inputs & namedInputs

The inputs array tells Nx what to consider to determine whether a particular invocation of a script should be a cache hit or not. There are three types of inputs:

Filesets

Examples:

  • {projectRoot}/**.*.ts
  • same as {fileset: "{projectRoot}/**/*.ts"}
  • {workspaceRoot}/jest.config.ts
  • same as {fileset: "{workspaceRoot}/jest.config.ts}
inputs syntax

The inputs and namedInputs are parsed with the following rules:

  1. {projectRoot} and {workspaceRoot} are replaced with the appropriate path
  2. A ^ character at the beginning of the string means this entry applies to the project dependencies of the project, not the project itself.
  3. Everything else is processed with the minimatch library

Runtime Inputs

Nx will execute the command specified by runtime inputs and use the result when calculating hashes.

Example:

1{ 2 "targets": { 3 "build": { 4 "executor" : "@nx/js:tsc", 5 "inputs" : [{"runtime": "node -v"}] 6 } 7 } 8} 9
Nx 15 and lower use @nrwl/ instead of @nx/

Note: the result is hashed, so it is never displayed.

Env Variables

Nx will read the environment variable specified by env inputs and use it when calculating hashes.

Example:

1{ 2 "targets": { 3 "build": { 4 "executor" : "@nx/js:tsc", 5 "inputs" : [{"env": "DEMO_VAR"}] 6 } 7 } 8} 9
Nx 15 and lower use @nrwl/ instead of @nx/

Note: the value is hashed, so it is never displayed.

External Dependencies

For official plugins, Nx intelligently finds a set of external dependencies which it hashes for the target. nx:run-commands is an exception to this. Because you may specify any command to be run, it is not possible to determine which, if any, external dependencies are used by the target. To be safe, Nx assumes that updating any external dependency invalidates the cache for the target.

Note: Community plugins are also treated like nx:run-commands

This input type allows you to override this cautious behavior by specifying a set of external dependencies to hash for the target.

Examples:

Targets that only use commands natively available in the terminal will not depend on any external dependencies. Specify an empty array to not hash any external dependencies.

1{ 2 "targets": { 3 "copyFiles": { 4 "inputs": [ 5 { 6 "externalDependencies": [] 7 } 8 ], 9 "command": "cp src/assets dist" 10 } 11 } 12} 13

If a target uses a command from an npm package, that package should be listed.

1{ 2 "targets": { 3 "copyFiles": { 4 "inputs": [ 5 { 6 "externalDependencies": ["lerna"] 7 } 8 ], 9 "command": "npx lerna publish" 10 } 11 } 12} 13

Dependent tasks output

This input allows us to depend on the output, rather than the input of the dependent tasks. We can specify the glob pattern to match only the subset of the output files. The transitive parameter defines whether the check and the pattern should be recursively applied to the dependent tasks of the child tasks.

Examples:

1{ 2 "namedInputs": { 3 "default": ["{projectRoot}/**/*", "sharedGlobals"], 4 "production": ["default", "!{projectRoot}/**/*.spec.ts"], 5 "deps": [{ "dependentTasksOutputFiles": "**/*.d.ts", "transitive": true }] 6 }, 7 "targetDefaults": { 8 "build": { 9 "dependsOn": ["^build"], 10 "inputs": ["production", "deps"] 11 } 12 } 13} 14

Named Inputs

Examples:

  • inputs: ["production"]
  • same as "inputs": [{"input": "production", "projects": "self"}] in versions prior to Nx 16, or "inputs": [{"input": "production"}] after version 16.

Often the same glob will appear in many places (e.g., prod fileset will exclude spec files for all projects). Because keeping them in sync is error-prone, we recommend defining namedInputs, which you can then reference in all of those places.

Using ^

Examples:

  • inputs: ["^production"]
  • same as inputs: [{"input": "production", "projects": "dependencies"}] prior to Nx 16, or "inputs": [{"input": "production", "dependencies": true }] after version 16.

Similar to dependsOn, the "^" symbols means "dependencies". This is a very important idea, so let's illustrate it with an example.

1{ 2 "targets": { 3 "test": { 4 "inputs": ["default", "^production"] 5 } 6 } 7} 8

The configuration above means that the test target depends on all source files of a given project and only prod sources (non-test sources) of its dependencies. In other words, it treats test sources as private.

nx.json reference

inputs and namedInputs are also described in the nx.json reference

Customizing inputs and namedInputs

This guide walks through a few examples of how to customize inputs and namedInputs

Outputs

Targets may define outputs to tell Nx where the target is going to create file artifacts that Nx should cache. "outputs": ["{workspaceRoot}/dist/libs/mylib"] tells Nx where the build target is going to create file artifacts.

This configuration is usually not needed. Nx comes with reasonable defaults (imported in nx.json) which implement the configuration above.

Specifically, by default, the following locations are cached for builds:

  • {workspaceRoot}/dist/{projectRoot},
  • {projectRoot}/build,
  • {projectRoot}/dist,
  • {projectRoot}/public

Basic Example

Usually, a target writes to a specific directory or a file. The following instructs Nx to cache dist/libs/mylib and build/libs/mylib/main.js:

1{ 2 "targets": { 3 "build": { 4 "outputs": [ 5 "{workspaceRoot}/dist/libs/mylib", 6 "{workspaceRoot}/build/libs/mylib/main.js" 7 ] 8 } 9 } 10} 11

Specifying Globs

Sometimes, multiple targets might write to the same directory. When possible it is recommended to direct these targets into separate directories.

1{ 2 "targets": { 3 "build-js": { 4 "outputs": ["{workspaceRoot}/dist/libs/mylib/js"] 5 }, 6 "build-css": { 7 "outputs": ["{workspaceRoot}/dist/libs/mylib/css"] 8 } 9 } 10} 11

But if the above is not possible, globs (parsed by the GlobSet Rust library) can be specified as outputs to only cache a set of files rather than the whole directory.

1{ 2 "targets": { 3 "build-js": { 4 "outputs": ["{workspaceRoot}/dist/libs/mylib/**/*.{js,map}"] 5 }, 6 "build-css": { 7 "outputs": ["{workspaceRoot}/dist/libs/mylib/**/*.css"] 8 } 9 } 10} 11

More advanced patterns can be used to exclude files and folders in a single line

1{ 2 "targets": { 3 "build-js": { 4 "outputs": ["{workspaceRoot}/dist/libs/!(cache|.next)/**/*.{js,map}"] 5 }, 6 "build-css": { 7 "outputs": ["{workspaceRoot}/dist/libs/mylib/**/!(secondary).css"] 8 } 9 } 10} 11

dependsOn

Targets can depend on other targets. This is the relevant portion of the configuration file:

1{ 2 "targets": { 3 "build": { 4 "dependsOn": ["^build"] 5 }, 6 "test": { 7 "dependsOn": ["build"] 8 } 9 } 10} 11

A common scenario is having to build dependencies of a project first before building the project. This is what the "dependsOn": ["^build"] property of the build target configures. It tells Nx that before it can build mylib it needs to make sure that mylib's dependencies are built as well. This doesn't mean Nx is going to rerun those builds. If the right artifacts are already in the right place, Nx will do nothing. If they aren't in the right place, but they are available in the cache, Nx will retrieve them from the cache.

Another common scenario is for a target to depend on another target of the same project. For instance, "dependsOn": ["build"] of the test target tells Nx that before it can test mylib it needs to make sure that mylib is built, which will result in mylib's dependencies being built as well.

You can also express task dependencies with an object syntax:

1{ 2 "targets": { 3 "build": { 4 "dependsOn": [ 5 { 6 "projects": "dependencies", // "dependencies" or "self" 7 "target": "build", // target name 8 "params": "ignore" // "forward" or "ignore", defaults to "ignore" 9 } 10 ] 11 } 12 } 13} 14

Examples

You can write the shorthand configuration above in the object syntax like this:

1{ 2 "targets": { 3 "build": { 4 "dependsOn": [{ "projects": "dependencies", "target": "build" }] 5 }, 6 "test": { 7 "dependsOn": [{ "projects": "self", "target": "build" }] 8 } 9 } 10} 11

With the expanded syntax, you also have a third option available to configure how to handle the params passed to the target. You can either forward them or you can ignore them (default).

1{ 2 "targets": { 3 "build": { 4 // forward params passed to this target to the dependency targets 5 "dependsOn": [ 6 { "projects": "dependencies", "target": "build", "params": "forward" } 7 ] 8 }, 9 "test": { 10 // ignore params passed to this target, won't be forwarded to the dependency targets 11 "dependsOn": [ 12 { "projects": "dependencies", "target": "build", "params": "ignore" } 13 ] 14 }, 15 "lint": { 16 // ignore params passed to this target, won't be forwarded to the dependency targets 17 "dependsOn": [{ "projects": "dependencies", "target": "build" }] 18 } 19 } 20} 21

This also works when defining a relation for the target of the project itself using "projects": "self":

1{ 2 "targets": { 3 "build": { 4 // forward params passed to this target to the project target 5 "dependsOn": [ 6 { "projects": "self", "target": "pre-build", "params": "forward" } 7 ] 8 } 9 } 10} 11

Additionally, when using the expanded object syntax, you can specify individual projects in version 16 or greater.

1{ 2 "targets": { 3 "build": { 4 // Run is-even:pre-build and is-odd:pre-build before this target 5 "dependsOn": [ 6 { "projects": ["is-even", "is-odd"], "target": "pre-build" } 7 ] 8 } 9 } 10} 11

This configuration is usually not needed. Nx comes with reasonable defaults (imported in nx.json) which implement the configuration above.

tags

You can annotate your projects with tags as follows:

package.json
1{ 2 "name": "mylib", 3 "nx": { 4 "tags": ["scope:myteam"] 5 } 6} 7

You can configure lint rules using these tags to, for instance, ensure that libraries belonging to myteam are not depended on by libraries belong to theirteam.

implicitDependencies

Nx uses powerful source-code analysis to figure out your workspace's project graph. Some dependencies cannot be deduced statically, so you can set them manually like this. The implicitDependencies property is parsed with the minimatch library, so you can review that syntax for more advanced use cases.

package.json
1{ 2 "name": "mylib", 3 "nx": { 4 "implicitDependencies": ["anotherlib"] 5 } 6} 7

You can also remove a dependency as follows:

package.json
1{ 2 "name": "mylib", 3 "nx": { 4 "implicitDependencies": ["!anotherlib"] # regardless of what Nx thinks, "mylib" doesn't depend on "anotherlib" 5 } 6} 7

An implicit dependency could also be a glob pattern:

package.json
1{ 2 "name": "mylib", 3 "nx": { 4 "implicitDependencies": ["shop-*"] # "mylib" depends on all projects beginning with "shop-" 5 } 6} 7

Including package.json files as projects in the graph

Any package.json file that is referenced by the workspaces property in the root package.json file will be included as a project in the graph. If you are using Lerna, projects defined in lerna.json will be included. If you are using pnpm, projects defined in pnpm-workspace.yml will be included.

If you want to ignore a particular package.json file, exclude it from those tools. For example, you can add !packages/myproject to the workspaces property.

Ignoring package.json scripts

Nx merges package.json scripts with your targets that are defined in project.json. If you only wish for some scripts to be used as Nx targets, you can specify them in the includedScripts property of the project's package.json.

1{ 2 "name": "my-library", 3 "version": "0.0.1", 4 "scripts": { 5 "build": "tsc", 6 "postinstall": "node ./tasks/postinstall" 7 }, 8 "nx": { 9 "includedScripts": ["build"] 10 } 11} 12