Heft The Build System You Didn’t Know You Needed
— Code — 4 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:
- Loads
heft.json
– Defines plugin and task config - Initializes plugins – Each plugin can contribute tasks
- Runs tasks – Like
compile
,test
,lint
, or custom - 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-domnpm install --save-dev @types/react @types/react-dom
Optional (for test + lint):
npm install --save-dev jest ts-jest eslintnpm 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 testnpx heft lint
Takeaways
Feature | Supported 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
- Heft Docs: https://rushstack.io/pages/heft/overview/
- Rush (monorepo): https://rushjs.io/
- GitHub: https://github.com/microsoft/rushstack/tree/main/apps/heft