Read this first 🎈
Here's a quick summary of the most important concepts of Heft:
In Heft's terminology, an "action" is command-line verb, as formalized by Rush Stack's ts-command-line system. Use
heft --help to see the available actions. The
run actions are provided by Heft itself; the others are produced by your heft.json configuration.
Example: A shell command
heft test --clean is invoking the
Note: Early releases of Heft also used the word "action" for
eventActionsin heft.json. This terminology is no longer used.
Actions support various command-line "parameters" for adjusting behavior. Some parameters are defined by Heft itself; others are contributed by Heft plugins.
Example: A shell command
heft test --clean is using the
Heft "tasks" are defined in the
tasksByName section of a heft.json config file for your project. Tasks typically read input files and/or generate output files, often by invoking a familiar tool such as TypeScript or ESLint. Each task loads a Heft task plugin (see below). It's possible for two different tasks to load the same plugin. Tasks can depend on each other, which determines scheduling order.
@rushstack/heft-web-rig configuration defines a task called
A "phase" is an arrangement of Heft tasks, defined in the
phasesByName section of a heft.json config file for your project. In that file, phases are given names such as
test. Defining a phase creates two corresponding command-line actions. For example, the
test phase produces a
heft test and
heft test-watch action. The
-watch variant is for interactive watch mode, for example a localhost dev server.
If tasks belong to the same phase, they can share memory objects for optimization; otherwise, they must only communicate by writing files to disk. This requirement supports integration with Rush phases which may run at different times or on different computers, communicating via the Rush build cache.
@rushstack/heft-web-rig configuration defines a
build phase that incorporates a
Heft plugins are TypeScript classes that implement the
IHeftPlugin contract. There are two kinds of plugins:
- a task plugin can be loaded by heft.json tasks and provides their implementation
- a lifecycle plugin provides general functionality that is not specific to any task; for example, to collect timing metrics
A "plugin package" is an NPM package providing Heft plugins. The NPM package naming pattern is
heft-____-plugins (according to the number of plugins). Built-in plugins are loaded directly from the
See the Plugin package index for the list of official plugins.
@rushstack/heft-jest-plugin package implements jest-plugin.
Each plugin package includes a file heft-plug.json which is called the "plugin manifest." It describes the available plugins, their options, and their command-line parameters. Heft is data-driven, which means that such information can be discovered without executing any custom scripts. (Although scripted configuration is very popular, it has many problems such as unexpected performance costs, unpredictable behavior that hinders caching, and poor error messages.)
@rushstack/heft-jest-plugin package declares
jest-plugin in this manifest.
Heft plugins can register handlers for various events during the build lifecycle. The API terminology of "tapping" event "hooks" comes from Heft's usage of the tapable system, familiar from Webpack plugins.
Example: In Heft's source code, the IHeftTaskHooks interface exposes some hooks.
The main philosophy of Heft is to move build logic into plugin packages, so that your build process is defined by config files instead of program scripts. In a large monorepo, this greatly reduces maintenance costs, by ensuring that program scripts are developed as professional software and not ad hoc commands in a
The Rush Stack rig system goes a step further, optionally moving config files into a centralized NPM package called a "rig." Rigs define standardized configurations for your projects. In a large monorepo, they formalize the configurations that your build team has agreed to support. Heft also allows
devDependencies to be resolved from rig packages, reducing package.json clutter.
Example: @rushstack/heft-web-rig is Rush Stack's reference rig for web projects.
A single rig package can provide multiple "profiles" tailored for specific purposes. Profiles within a rig package share the same rigged
devDependencies, and may also share configuration via
@rushstack/heft-web-rig rig package currently defines two profiles,