Understanding Heft in SharePoint Framework 1.22 (Part 1)

What is Heft?

Heft is a modern, TypeScript-first build orchestrator developed by Microsoft as part of the Rush Stack project. It’s designed to replace traditional task runners like Gulp with a more efficient, scalable, and maintainable build system.

Key Features of Heft

  • TypeScript-First: Native TypeScript compilation without wrappers
  • Plugin-Based Architecture: Clean extensibility through lifecycle hooks
  • Parallel Execution: Tasks run concurrently when possible
  • Intelligent Caching: Faster incremental builds
  • Rig System: Share configuration across projects
  • Modern Tooling: Built-in support for Webpack 5, ESLint, Jest

Why Did Microsoft Choose Heft?

Microsoft moved from Gulp to Heft for several compelling reasons:

  1. Performance: Heft’s parallel task execution and intelligent caching significantly reduce build times
  2. Scalability: Better suited for monorepo scenarios and large-scale projects
  3. Type Safety: TypeScript-first approach provides better developer experience
  4. Maintainability: Plugin architecture is cleaner than Gulp’s stream-based approach
  5. Modern Stack: Native support for latest tooling (Webpack 5, ESLint 9.x, TypeScript 5.x)

Important

Heft is ONLY supported in SPFx 1.22 and later. Projects built with SPFx 1.21.1 and earlier use Gulp-based toolchain.

Gulp vs Heft: Understanding the Shift

Before diving into Heft, let’s understand how it differs from the traditional Gulp-based approach.

Architecture Comparison

Aspect Gulp (SPFx ≤1.21.1) Heft (SPFx 1.22+)
Build Orchestrator Gulp 4.x Heft (Rush Stack)
Configuration gulpfile.js config/heft.json
Task Definition JavaScript streams Plugin-based phases
Customization Gulp tasks, build.rig.js Heft plugins, webpack patches
TypeScript gulp-typescript plugin Native Heft TypeScript plugin
Webpack gulp-webpack wrapper Direct Webpack 5 integration
Config Management Scattered files Centralized rig system
Parallelization Limited Native parallel execution

Project Structure Comparison

The project structure has evolved significantly from Gulp to Heft. Here’s a comparison:

Legacy (SPFx ≤1.21.1)

plaintext
my-webpart/
├── .vscode/
├── config/
│ ├── config.json
│ ├── deploy-azure-storage.json
│ ├── package-solution.json
│ ├── serve.json
│ └── write-manifests.json
├── src/
├── .gitignore
├── .npmignore
├── .yo-rc.json
├── gulpfile.js
├── package-lock.json
├── package.json
├── README.md
└── tsconfig.json

Heft (SPFx 1.22+)

plaintext
my-webpart/
├── .vscode/
├── config/
│ ├── config.json
│ ├── deploy-azure-storage.json
│ ├── package-solution.json
│ ├── rig.json ⭐
│ ├── sass.json ⭐
│ ├── serve.json
│ ├── typescript.json ⭐
│ └── write-manifests.json
├── lib-commonjs/ ⭐
├── src/
├── .gitignore
├── .npmignore
├── .yo-rc.json
├── package-lock.json
├── package.json
├── README.md
└── tsconfig.json

Key Differences in Structure

Files Removed in Heft:

  • gulpfile.js - No longer needed; Heft manages build orchestration

New Files in Heft:

  • config/rig.json - Points to the shared SPFx rig package for centralized configuration
  • config/typescript.json - TypeScript compiler configuration overrides
  • lib-commonjs/ - CommonJS output directory for compiled TypeScript

Modified Files in Heft:

  • 🔄 config/sass.json - Now extends rig configuration instead of standalone settings

Understanding New Configuration Files

config/rig.json

Points to the shared @microsoft/spfx-web-build-rig package that contains common build configurations. This enables configuration inheritance and reduces boilerplate.

json
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
"rigPackageName": "@microsoft/spfx-web-build-rig"
}

config/typescript.json

Extends the rig’s TypeScript configuration with project-specific overrides.

json
{
"extends": "./node_modules/@microsoft/spfx-web-build-rig/profiles/library/config/typescript.json"
}

config/sass.json

Configures SASS compilation settings for your styles.

json
{
"extends": "@microsoft/spfx-web-build-rig/profiles/library/includes/sass.json"
}

Command Comparison

Task Gulp Command Heft Command
Development build gulp build heft build
Bundle¹ gulp bundle (included in build)
Production build gulp bundle --ship && gulp package-solution --ship heft build --production
Start dev server gulp serve heft start
Clean gulp clean heft clean
Run tests gulp test heft test
Dev deployment² (not available) heft dev-deploy
Create package gulp package-solution heft package-solution
Trust dev cert gulp trust-dev-cert heft trust-dev-cert
Untrust dev cert gulp untrust-dev-cert heft untrust-dev-cert
Deploy to Azure gulp deploy-azure-storage heft deploy-azure-storage

Notes:

  1. Bundle command: Heft doesn’t have a separate bundle command. The build and bundle processes are combined into a single heft build command.
  2. dev-deploy: New command in Heft that deploys built assets to a testing CDN for validating external loading during development.
  3. –ship vs –production: The --ship argument from Gulp has been replaced with --production in Heft for creating production deployments.

Getting Started with Heft

Creating a New SPFx Project with Heft

To create a new SPFx 1.22 project with Heft:

bash
# Install the latest Yeoman and SPFx generator
npm install -g yo @microsoft/generator-sharepoint

# Create a new project
yo @microsoft/sharepoint

# Select SPFx version 1.22 or later

Tip

The Yeoman generator automatically scaffolds projects with Heft when using SPFx 1.22+. No additional setup required!

Your First Heft Build

After creating your project:

bash
# Install dependencies
npm install

# Start development server
npm start
# or
heft start

# Build for production
heft build --production

# Create deployment package
heft package-solution --production

Migrating Existing Projects from Gulp to Heft

If you have an existing SPFx project using Gulp, here’s how to migrate:

Step 1: Update package.json

Update your SPFx dependencies to version 1.22 or later:

json
{
"dependencies": {
"@microsoft/sp-core-library": "1.22.0",
"@microsoft/sp-webpart-base": "1.22.0"
},
"devDependencies": {
"@microsoft/eslint-config-spfx": "1.22.0",
"@microsoft/eslint-plugin-spfx": "1.22.0",
"@microsoft/sp-module-interfaces": "1.22.0",
"@microsoft/spfx-heft-plugins": "1.22.0",
"@microsoft/spfx-web-build-rig": "1.22.0",
"@rushstack/heft": "1.1.2",
"typescript": "~5.8.0"
}
}

Key Changes:

  • ❌ Remove @microsoft/sp-build-web (Gulp-based build package)
  • ⭐ Add @microsoft/spfx-web-build-rig - Heft rig package with SPFx build configuration
  • ⭐ Add @microsoft/spfx-heft-plugins - SPFx-specific Heft plugins
  • ⭐ Add @rushstack/heft - Heft build orchestrator (v1.1.2)
  • 🔄 Update to @microsoft/eslint-config-spfx and @microsoft/eslint-plugin-spfx (replaces TSLint)
  • 🔄 Update TypeScript to ~5.8.0

Step 2: Remove Gulp Files

Delete the following files:

  • gulpfile.js
  • Any custom gulp tasks in gulp folder (if exists)

Step 3: Add Rig Configuration

Create config/rig.json:

json
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
"rigPackageName": "@microsoft/spfx-web-build-rig"
}

Step 4: Update Build Scripts

Update package.json scripts:

json
{
"scripts": {
"build": "heft build --production",
"clean": "heft clean",
"test": "heft test"
}
}

Step 5: Migrate Webpack Customizations

If you have config/webpack.js, convert it to webpack patches (covered in Part 2).

Step 6: Clean Install

bash
# Remove old dependencies
rm -rf node_modules package-lock.json

# Fresh install
npm install

# Test build
heft build

Important

Always test your migrated project thoroughly in a development environment before deploying to production.

The Rig System: The Heart of Heft Configuration

The most important file in a Heft-based SPFx project is config/rig.json:

json
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
"rigPackageName": "@microsoft/spfx-web-build-rig"
}

What is a Rig?

A rig is a reusable configuration package published to npm. Think of it as a shared template that contains all the base build configuration for SPFx projects.

Benefits of the Rig System:

  1. Consistency - All SPFx projects use the same build process
  2. Less Boilerplate - No need to duplicate configuration
  3. Easy Updates - Update rig version to get latest build improvements
  4. Best Practices - Microsoft maintains optimal settings
  5. Maintainability - Single source of truth for build config

How It Works:

plaintext
Your Project
↓ (references via rig.json)
@microsoft/spfx-web-build-rig
↓ (contains)
Base heft.json configuration
↓ (defines)
All SPFx build tasks (Sass, TypeScript, Webpack, etc.)

The rig contains the complete Heft configuration at:
node_modules/@microsoft/spfx-web-build-rig/profiles/default/config/heft.json

Your project inherits everything from this base configuration!

Pro Tip

You can inspect the complete inherited configuration by examining node_modules/@microsoft/spfx-web-build-rig/profiles/default/config/heft.json in your project. This helps understand what's happening under the hood!

Understanding the Build Pipeline

When you run heft build --production, here’s what happens:

plaintext
heft build --production

┌─────────────────────────────────────────────────┐
│ Phase: build │
├─────────────────────────────────────────────────┤
│ 1. set-browserslist-ignore-old-data-env-var │
│ 2. sass - Compile SCSS to CSS │
│ 3. typescript - Compile TS to JS │
│ 4. lint - Run ESLint │
│ 5. configure-webpack - Setup Webpack │
│ 6. webpack-patch - Apply customizations │
│ 7. webpack - Bundle JavaScript │
└─────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────┐
│ Phase: package-solution │
├─────────────────────────────────────────────────┤
│ - Generate .sppkg file │
└─────────────────────────────────────────────────┘

All these tasks are defined in the base rig and execute automatically!

Common Issues and Troubleshooting

Issue 1: “Cannot find module ‘@microsoft/sp-rig’”

Solution:

bash
npm install --save-dev @microsoft/sp-rig

Ensure your config/rig.json points to the correct rig package.

Issue 2: Build fails with “ENOENT: no such file or directory”

Solution:
Clean your project and rebuild:

bash
heft clean
rm -rf node_modules package-lock.json
npm install
heft build

Issue 3: “Webpack configuration not found”

Solution:
Remove any old config/webpack.js files. Heft uses webpack patches instead. Check config/rig.json is properly configured.

Issue 4: Performance issues during build

Tips for faster builds:

  • Use heft build (development) instead of --production during development
  • Enable incremental builds (enabled by default)
  • Increase Node.js memory: NODE_OPTIONS="--max-old-space-size=4096" heft build
  • Use heft clean sparingly

Issue 5: ESLint errors after migration

Solution:
Update your .eslintrc.js configuration to be compatible with the latest ESLint version. The rig provides base ESLint configuration.

Tip

For detailed error messages, run Heft with verbose logging: heft build --verbose

Conclusion

Heft represents a significant improvement over the traditional Gulp-based toolchain in SharePoint Framework. Its modern architecture, better performance, and clean extensibility make it the future of SPFx development.

Key Takeaways

  1. Heft is mandatory in SPFx 1.22+ (no more Gulp!)
  2. Rig system provides shared configuration and best practices
  3. Webpack patches replace webpack.config.js modifications
  4. Commands are simplified - npm start and npm run build
  5. Better performance through parallel execution and caching

What’s Next?

In Part 2 of this series, we’ll dive deep into building custom Heft plugins. You’ll learn:

  • Complete plugin architecture and lifecycle
  • Building a production-ready version incrementer plugin
  • TypeScript implementation with proper typing
  • Testing and debugging custom plugins
  • Best practices for plugin development

Resources

Official Documentation

Community Resources

Tools and Extensions

Questions or feedback? Leave a comment below or reach out on LinkedIn!

Author: Ejaz Hussain
Link: https://office365clinic.com/2025/12/15/understanding-heft-in-spfx-part1/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.