Skip to content
Petkir Blog
XLinkedinBluesky

Heft The Build System You Didn’t Know You Needed

Code4 min read

The Problem: Spaghetti Scripts in Frontend Projects

Many frontend projects grow organically. You start with a simple tsc, add eslint, jest, maybe webpack, and suddenly you're juggling a pile of npm scripts and CLI options.

Even worse: teams often create different build logic per project, even though the tooling is 90% the same.

This leads to:

  • Inconsistent build behaviors
  • Hard-to-maintain scripts
  • Onboarding pain

So what if we could have one standard build pipeline, with clean structure, plugin support, and TypeScript-first?

Enter: Heft.


What is Heft?

Heft is a task runner and build orchestrator developed by the RushStack team at Microsoft. It’s used in projects like Fluent UI, SPFx, and the Azure SDK.

It’s not another bundler. Instead, Heft focuses on orchestration:

  • It runs TypeScript builds
  • Integrates Jest, ESLint, and API Extractor
  • Allows custom tasks and plugins
  • Provides Rush support for monorepos
  • Scales well across enterprise-grade codebases

How does Heft work?

When you call npx heft, the following happens:

  1. Loads heft.json – Defines plugin and task config
  2. Initializes plugins – Each plugin can contribute tasks
  3. Runs tasks – Like compile, test, lint, or custom
  4. Shares state via build context and options

Tasks are just plugins. Heft doesn’t do anything unless tasks are defined.

You can imagine it like this:

Heft Core
└── Plugin: TypeScript Task
└── Plugin: Jest Task
└── Plugin: Webpack Task
└── Plugin: Custom Tasks (your code)

This modular architecture makes Heft ideal for enterprise build pipelines that need to scale across multiple teams.


Setting up Heft in a React App

Let’s walk through a real setup for a React + TypeScript project that uses Heft.

Project Structure

my-heft-app/
├── config/
│ ├── typescript.json
│ └── jest.config.json
├── src/
│ └── App.tsx
├── heft.json
├── tsconfig.json
└── package.json

Install Dependencies

npm install --save-dev @rushstack/heft typescript react react-dom
npm install --save-dev @types/react @types/react-dom

Optional (for test + lint):

npm install --save-dev jest ts-jest eslint
npm install --save-dev @rushstack/heft-jest-plugin @rushstack/heft-eslint-plugin

Configuration Files

heft.json

{
"$schema": "https://developer.microsoft.com/json-schemas/heft/heft.schema.json",
"heftVersion": "^0.63.0"
}

tsconfig.json

{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"jsx": "react-jsx",
"strict": true,
"esModuleInterop": true,
"outDir": "lib"
},
"include": ["src"]
}

config/typescript.json

{
"$schema": "https://developer.microsoft.com/json-schemas/heft/typescript.schema.json",
"disableTscWatch": true
}

src/App.tsx

import React from "react";
export const App = () => <h1>Hello from Heft + React</h1>;

Build the Project

npx heft build

Outputs compiled .js into /lib.


Extending Heft – Custom Tasks

You can build your own Heft tasks by writing a plugin.

Example: A greet task

build-plugins/greet-plugin/GreetPlugin.ts

import {
HeftConfiguration,
HeftSession,
IHeftPlugin
} from '@rushstack/heft';
export default class GreetPlugin implements IHeftPlugin {
public apply(heftSession: HeftSession, heftConfig: HeftConfiguration): void {
heftSession.registerTask({
taskName: "greet",
run: async (taskSession) => {
taskSession.logger.terminal.writeLine("👋 Hello from your custom Heft task!");
}
});
}
}

Register in heft.json:

{
"plugins": [
{
"plugin": "./build-plugins/greet-plugin/GreetPlugin.js",
"options": {}
}
]
}

Run it:

npx heft greet

Integration with Jest and ESLint

config/jest.config.json

{
"$schema": "https://developer.microsoft.com/json-schemas/heft/jest.schema.json",
"preset": "ts-jest"
}

Then run:

npx heft test
npx heft lint

Takeaways

FeatureSupported by Heft?
TypeScript✅ Built-in
React✅ Supported via JSX config
ESLint✅ Via plugin
Jest✅ Via plugin
Custom Tasks✅ Simple to write
Rush Integration✅ Native support

Summary

If you’ve ever struggled with:

  • too many npm scripts
  • maintaining consistent build logic
  • scaling React/TypeScript projects in a team

Then Heft is a rock-solid foundation for your build process.

It’s part of the RushStack ecosystem, backed by Microsoft, and it integrates smoothly with other tools like API Extractor, Jest, and ESLint. Plus: you can write custom tasks with minimal boilerplate.

✅ Try it for small projects.
✅ Scale it with Rush for monorepos.
✅ Extend it when needed.


Links