nx/docs/shared/concepts/customizing-inputs.md
2022-11-15 15:48:29 -05:00

156 lines
6.8 KiB
Markdown

# Customizing Inputs and Named Inputs
The `inputs` property of a task allows you to define under what conditions the cache for that task should be invalidated and the task should be run again. Tasks can have `inputs` defined for them [globally in the `nx.json` file](/reference/nx-json#inputs-&-namedinputs) or [on a per-project basis in the project configuration](/reference/project-configuration#inputs-&-namedinputs). Those `inputs` can be `fileset`s, `runtime` inputs or `env` variables.
If you find yourself reusing the same `inputs` definitions, you can instead create a `namedInput` in the project configuration or `nx.json` and use that `namedInput` in your `inputs` array.
Knowing the syntax doesn't always explain how you would use the feature, so here are two scenarios explaining how to customize `inputs` to match your particular set up.
## Defaults
If you don't specify any `inputs`, Nx uses as inputs every file in the task's project and every file in that project's dependencies. It's the same as writing this:
```jsonc
{
"namedInputs": {
"default": ["{projectRoot}/**/*"]
},
"targetDefaults": {
"build": {
"inputs": ["default", "^default"]
}
}
}
```
This default behavior works and will always give you correct output, but it might re-run a task in some cases where the cache could have been used instead. Modifying `inputs` and `namedInputs` is all about getting the most you can out of the caching mechanism.
## Scenario 1: React App
Let's say we have a repo with two projects. There's a React app (`react-app`) that depends on a React UI library (`ui-library`).
### Global Settings
In the root `nx.json` file, we can set the following `namedInputs`:
```jsonc {% fileName="nx.json" %}
{
"namedInputs": {
"sharedGlobals": ["{workspaceRoot}/babel.config.json"],
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"production": [
"default",
"!{projectRoot}/**/*.spec.ts",
"!{projectRoot}/**/*.md",
"!{projectRoot}/tsconfig.spec.json",
"!{projectRoot}/jest.config.ts",
"!{projectRoot}/.eslintrc.json"
]
}
}
```
This configuration defines three `namedInputs`.
- `sharedGlobals` contains root level files that should invalidate the cache for all projects. Note that `tsconfig.base.json` and the `package.json` lock files are handled behind the scenes by Nx so that when you modify the specific properties that affect your project, the cache is invalidated.
- `default` contains every file in the project and everything defined in `sharedGlobals`
- `production` starts with every file in `default`, but removes `.spec.ts` files, markdown files and some project-specific config files.
These names are not hard-coded. You can add your own `namedInputs` or rename these as you see fit.
With these `namedInputs` in place, we can set default `inputs` for project targets in `nx.json`:
```jsonc {% fileName="nx.json" %}
{
"namedInputs": {
"sharedGlobals": [
/* ... */
],
"default": [
/* ... */
],
"production": [
/* ... */
]
},
"targetDefaults": {
"build": {
"inputs": ["production", "^production"],
"dependsOn": ["^build"]
},
"test": {
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"]
}
}
}
```
In this configuration, `build` needs to be re-run if the project's `production` files are changed or the dependencies' `production` files are changed. The `"dependsOn": ["^build"]` setting ensures that the output files of the dependencies are correct, but it does not tell Nx to re-run this project's build target when those outputs change. That's why `"^production"` is needed in the `inputs` array.
Note that we are using `^production` instead of `^default` because changing test files of a dependency should not invalidate the build cache for this project.
The `test` target cache is invalidated if test or production code is changed in this project (`default`) or if production code is changed in a dependency `^production`. The tests also need to be run again if the root level `jest.preset.js` file is modified.
### Project Settings
In the `ui-library` library, we have some `*.spec.tsx` files that we don't want to count as production files. We can modify the project configuration to account for this:
```jsonc {% command="ui-library/project.json" %}
{
"namedInputs": {
"production": [
// copied this definition from nx.json
"default",
"!{projectRoot}/**/*.spec.ts",
"!{projectRoot}/**/*.spec.tsx", // added this line
"!{projectRoot}/**/*.md",
"!{projectRoot}/tsconfig.spec.json",
"!{projectRoot}/jest.config.ts",
"!{projectRoot}/.eslintrc.json"
]
}
}
```
Note that I need to copy the entire definition of `production` from `nx.json`. This entry overwrites the existing `production` entry defined in `nx.json`, but `default` and `sharedGlobals` are inherited. Now when I modify a `spec.tsx` file in `ui-library`, the build for `ui-library` is unaffected and the build for `react-app` is unaffected.
{% callout type="note" title="Modifying production in nx.json" %}
You could also handle this scenario by modifying the `production` definition in the `nx.json` so that it applies to all projects in the repo. In fact, the defaults created by Nx do exactly that: `"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)"`. This is a complex glob expression though and is not particularly helpful for explaining the concepts of `inputs` and `namedInputs`.
{% /callout %}
The `build` and `test` `inputs` do not need to be modified at the project level, since the defaults defined at the root are still correct.
## Scenario 2: Generated Documentation Site
Let's say you have a repo with two projects, a `docs-site` app that contains all the code for rendering a documentation site and a `content` library that contains markdown files that are used as the content of the site.
The `content` library has a node script `.ts` file that is used to check through the markdown files for internal broken links. The `test` target looks like this:
```jsonc
{
"targets": {
"test": {
"inputs": ["default", "^production"],
"executor": "nx:run-commands",
"command": "ts-node ./check-for-broken-links.ts"
}
}
}
```
Note that we are overwriting the default `inputs` for `test` because changes to the root `jest.preset.js` file shouldn't affect this project's tests.
This library's `production` definition should look like this:
```jsonc
{
"namedInputs": {
"production": ["default", "!{projectRoot}/**/*.ts"]
}
}
```
This ensures that the `.md` files are included in the `production` file set, but the `check-for-broken-links.ts` script is not. Now changes to a markdown file in `content` will force a re-build of `docs-site`, even though changes to markdown files in `docs-site` will not force a re-build.