Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,52 @@ Versioning](https://semver.org/spec/v2.0.0.html).
or when another script that depends on it is ready to run. A service is stopped
when all scripts that depend on it have finished, or when Wireit is exited.

- Added `"triggersRerun": false` setting to dependencies.

By default, the fingerprint of a script includes the fingerprints of its
dependencies. This means a script will re-run whenever one of its dependencies
re-runs, even if the output produced by the dependency didn't actually change.

Now, if a dependency is annotated with `"triggersRerun": false`, then the
fingerprint of that dependency will no longer be included in the script's own
fingerprint. This means a script won't neccessarily re-run just because a
dependency re-ran — though Wireit will still always run the dependency first
if it is not up-to-date.

Using `"triggersRerun": false` can result in faster builds thanks to fewer
re-runs, but it is very important to specify all of the input files generated
by the dependency which the script depends on in the `files` array.

Example:

```json
{
"wireit": {
"build": {
"command": "tsc",
"files": ["tsconfig.json", "src/**/*.ts"],
"output": "lib/**",
},
"bundle": {
"command": "rollup -c",
"files": ["rollup.config.json", "lib/**/*.js", "!lib/test"],
"output": "dist/bundle.js",
"dependencies": {
[
"script": "build",
"triggersRerun": false
]
}
}
}
}
```

### Changed

- Added string length > 0 requirement to the `command`, `dependencies`, `files`,
`output`, and `packageLocks` properties in `schema.json`.

### Fixed

- Fixed memory leak in watch mode.
Expand Down
102 changes: 97 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- [Dependencies](#dependencies)
- [Vanilla scripts](#vanilla-scripts)
- [Cross-package dependencies](#cross-package-dependencies)
- [Triggers re-run](#triggers-re-run)
- [Parallelism](#parallelism)
- [Extra arguments](#extra-arguments)
- [Input and output files](#input-and-output-files)
Expand Down Expand Up @@ -168,6 +169,78 @@ workspaces, as well as in other kinds of monorepos.
}
```

### Triggers re-run

By default, whenever a dependency runs, the script that depends on it will be
marked stale and need to re-run too — regardless of whether the dependency
actually produced new or relevant output.

This is a safe default because it means you aren't required to specify the input
files for every script when those input files are generated by a dependency.
However, it comes with the tradeoff that scripts will sometimes re-run even when
none of their input files changed.

To change this behavior and further optimize your build, you can use the
`triggersRerun` setting to tell Wireit that all of the input files needed from
a dependency are declared in the `files` array. Now, Wireit won't assume that a
script was stale just because its dependency ran.

To enable this setting, create an object for your dependency instead of a plain
string, and set `triggersRerun` to `false`:

```json
{
"wireit": {
"A": {
"dependencies": [
{
"script": "B",
"triggersRerun": false
}
]
}
}
}
```

In the following example, `bundle` has a dependency on `build` with
`triggersRerun: false`. Importantly, it also includes `lib/**/*.js` in its
`files` array, which are the specific outputs from `tsc` that `rollup` consumes.
Including these input files wasn't neccessary before, but with
`triggersRerun: false` it is now critical.

```json
{
"scripts": {
"build": "wireit",
"bundle": "wireit"
},
"wireit": {
"build": {
"command": "tsc",
"files": ["src/**/*.ts", "tsconfig.json"],
"output": ["lib/**"]
},
"bundle": {
"command": "rollup -c",
"dependencies": [
{
"script": "build",
"triggersRerun": false
}
],
"files": ["rollup.config.json", "lib/**/*.js", "!lib/test"],
"output": ["dist/bundle.js"]
}
}
}
```

The advantage of this configuration is that if `tsc` re-runs but doesn't produce
different `.js` files (for example, if it only produced different `.d.ts`
files), then `rollup` won't need to re-run. We've also excluded the `lib/test`
directory, because we know test files aren't included in our bundles.

## Parallelism

Wireit will run scripts in parallel whenever it is safe to do so according to
Expand Down Expand Up @@ -408,26 +481,45 @@ expected to exit by itself, set `"service": true`.
"command": "node my-server.js",
"service": true,
"files": ["server-config.json"],
"dependencies": ["build:server", "build:assets"]
"dependencies": [
"build:server",
{
"script": "build:assets",
"triggersRerun": false
}
]
}
}
}
```

### Service lifetime

If a service is run _directly_ (e.g. `npm run serve`), then it will stay running
until the user kills Wireit (e.g. `Ctrl-C`).

If a service is a _dependency_ of one or more other scripts, then it will start
up before any depending script runs, and will shut down after all depending
scripts finish.

### Service restarts

In watch mode, a service will be restarted whenever one of its input files or
dependencies change.
dependencies change, except for dependencies with
[`triggersRerun: false`](#re-run-on-change).

Use `triggersRerun: false` when the output of a dependency is read dynamically
for each request handled by the service. For example, the static assets of a web
server can often be annotated with `triggersRerun: false`.

### Service output

Services cannot have `output` files, because there is no way for Wireit to know
when a service has finished writing its output. If you have a service that
produces output, you should define a non-service script that depends on it, and
which exits when the service's output is complete.
when a service has finished writing its output.

If you have a service that produces output, you should define a _non-service_
script that depends on it, and which exits when the service's output is
complete.

## Failures and errors

Expand Down
34 changes: 29 additions & 5 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,57 @@
},
"command": {
"markdownDescription": "The command to run.\n\nThis is a shell command that will be executed, with all binaries from npm dependencies and devDependencies available.\n\nFor example:\n\n```json\n\"command\": \"tsc\"\n```\n\nFor more info, see https://docs.npmjs.com/cli/v8/using-npm/scripts#environment",
"type": "string"
"type": "string",
"minLength": 1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh nice

},
"dependencies": {
"markdownDescription": "Other npm scripts that will run before this one.\n\nThese scripts do not have to use wireit.\n\nDependencies can refer to scripts in other npm packages by using a relative path with the syntax `<relative-path>:<script-name>`. All cross-package dependencies should start with a `\".\"`. Cross-package dependencies work well for npm workspaces, as well as in other kinds of monorepos.\n\nFor example:\n\n```json\n\"dependencies\": [\n \"build\",\n \"./packages/foo:build\"\n]\n```\n\nFor more info, see https://github.com/google/wireit#dependencies",
"items": {
"type": "string"
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "object",
"required": ["script"],
"properties": {
"script": {
"markdownDescription": "The name of the script (see `dependencies`).",
"type": "string",
"minLength": 1
},
"triggersRerun": {
"markdownDescription": "When `true` (the default), whenever this dependency runs, this script (the dependent) will be marked stale and need to re-run too, regardless of whether the dependency produced new or relevant output. When `false` Wireit won't assume that the dependent is stale just because the dependency ran. This can reduce unnecessary re-building (or restarting in the case of services) when `files` captures all of the relevant output of the dependency.\n\nFor more info, see https://github.com/google/wireit#re-run-on-change",
"type": "boolean"
}
}
}
]
},
"type": "array"
},
"files": {
"markdownDescription": "The files that this script depends on.\n\nThese are the files that are watched when run with the `watch` argument. They are also used to determine if a script is stale or if its files and dependencies haven't changed and execution can be skipped.\n\nDon't specify `files` unless the array of files (and `dependencies`) are the only things that this script depends on. For example, a script that fetches data over the internet should not have a files array.\n\nThis should be a list of package-relative paths to files, or glob patterns. See https://github.com/google/wireit#glob-patterns for more info on the format of glob patterns.\n\nFor example:\n\n```json\n\"files\": [\n \"src/**/*.ts\"\n]\n```",
"items": {
"type": "string"
"type": "string",
"minLength": 1
},
"type": "array"
},
"output": {
"markdownDescription": "The files that this script writes.\n\nThese are the files that are deleted before the script is executed (set `clean` to customize this behavior), and these are the files that are cached if `files` is specified.\n\nThis should be a list of package-relative paths to files, or glob patterns. See https://github.com/google/wireit#glob-patterns for more info on the format of glob patterns.\n\nFor example:\n\n```json\n\"output\": [\n \"lib/**/*\",\n \"!lib/bundle.js\"\n]\n```",
"items": {
"type": "string"
"type": "string",
"minLength": 1
},
"type": "array"
},
"packageLocks": {
"markdownDescription": "By default, Wireit automatically treats package-lock.json files in the package directory, plus all parent directories, as input files. This is useful because installing or upgrading your dependencies can affect the behavior of your scripts, so it's important to re-run them whenever your dependencies change.\n\nIf you are using an alternative package manager instead of npm, then your package lock files might be named something else.\n\nFor more info, see: https://github.com/google/wireit#package-locks",
"items": {
"type": "string"
"type": "string",
"minLength": 1
},
"type": "array"
},
Expand Down
Loading