Migrate from Gulp based to Heft based Toolchain in SharePoint Framework (SPFx)

If you’ve been building SharePoint Framework solutions for a while, you already know Gulp. It’s been the backbone of every SPFx project since day one — running your builds, serving the workbench, packaging your .sppkg files. But that era is officially over.

With SPFx v1.22, Microsoft replaced the Gulp-based toolchain with Heft — a config-driven build orchestrator from the Rush Stack ecosystem. Starting with SPFx v1.23, all new projects will use Heft by default. And by v1.24, the Gulp-based pipeline will be officially unsupported.

So if you have existing projects still running on Gulp, now is the time to migrate. In this tutorial, I will explain how to migrate from a Gulp-based to a Heft-based toolchain in the SharePoint Framework (SPFx) step by step.

What is Heft in SharePoint Framework?

In SPFx (SharePoint Framework)Heft is basically a build and task management tool that helps run and organize all the behind-the-scenes processes when you develop a SharePoint solution.

Think of Heft as a modern replacement for older tools like Gulp in SPFx. Starting from SPFx v1.22, Microsoft officially switched from Gulp to Heft to make builds cleaner and faster.

When you’re building an SPFx project, a lot of things need to happen automatically:

  • Compile TypeScript → JavaScript
  • Bundle your code
  • Run linting (check code quality)
  • Execute tests
  • Build the final package ready for SharePoint

Heft handles all of this automatically — you just run one command like heft build or heft start, and it takes care of the rest behind the scenes.

Instead of writing custom task scripts like you used to with Gulp, Heft uses simple JSON configuration files to define what to do, making your project easier to maintain and understand.

A new SPFx project already comes pre-configured with Heft through something called a rig (a shared settings package). So you don’t need to set anything up yourself — it just works out of the box.

Here’s a quick comparison between Gulp and Heft.

AreaGulp (Legacy)Heft (SPFx v1.22+)
Core modelCustom JS tasks in gulpfile.jsConfig-driven with plugins and rigs
ExtensibilityWrite custom tasks per projectUse Heft plugins or patch files
PerformanceSequential tasks, no cachingIncremental builds and caching
Config locationScattered across gulpfile.jsCentralized JSON files (heft.json, etc.)
ScaleHard to keep consistent across reposBuilt to scale with Rush Stack monorepos

Heft makes SPFx development cleaner and more modern by replacing the old Gulp-based system with a structured, configuration-driven approach.

Check out Set Up Your SharePoint Framework (SPFx) Development Environment using Heft Toolchain

Before You Start — A Few Things to Check

Don’t jump straight to uninstalling packages. Do these first:

  • Back up your project. Either copy the folder or make sure all your code is committed to source control. The migration makes sweeping changes to your config files and package.json.
  • Check your Node.js version. SPFx v1.22 requires Node v22. Run node -v to confirm. If you’re on an older version, update first.
  • Check for gulp customizations. Open your gulpfile.js and look for any custom tasks — things like build.configureWebpack.mergeConfig()build.rig.addPreBuildTask(), or custom copy/lint steps. You’ll need to translate these to Heft plugins after the migration. Note these down before you delete anything.

Migrate from Gulp based to Heft based Toolchain in SPFx

Follow the steps below to migrate from Gulp based to Heft based Toolchain in SharePoint Framework (SPFx).

Step 1: Uninstall the Gulp Toolchain

The first thing to do is rip out the old Gulp-based packages. Run this command from your project root:

npm uninstall @microsoft/sp-build-web ajv gulp
uninstall gulp-cli

Next, uninstall the TypeScript compiler wrapper. The default SPFx v1.21.1 project uses TypeScript 5.3, so:

npm uninstall @microsoft/rush-stack-compiler-5.3

If your project uses a different TypeScript version, replace 5.3 with whatever version you have. Check your package.json devDependencies — look for @microsoft/rush-stack-compiler-*.

install specific version of gulp

Step 2: Install the Heft Toolchain

Now install all the Heft-related packages your project needs:

npm install @microsoft/spfx-web-build-rig@1.22.1 @microsoft/spfx-heft-plugins@1.22.1 @microsoft/eslint-config-spfx@1.22.1 @microsoft/eslint-plugin-spfx@1.22.1 @microsoft/sp-module-interfaces@1.22.1 @rushstack/eslint-config@4.5.2 @rushstack/heft@1.1.2 @types/heft-jest@1.0.2 @typescript-eslint/parser@8.46.2 --save-dev --save-exact --force

That --force flag is there because some peer dependency conflicts can pop up during migration. It’s fine to use here — you’re intentionally replacing the old toolchain.

If you also want to upgrade TypeScript to v5.8 (optional but recommended), run:

npm install typescript@~5.8.0 --save-dev
spfx gulp migration with heft

Heads up: If you run into issues installing TypeScript v5.8 during migration, you can skip this for now. The toolchain works fine with TypeScript v5.3 too.

Step 3: Update Your NPM Scripts

Open your package.json and replace the old Gulp-based scripts with Heft equivalents. Find the scripts section and update it like this:

{
"scripts": {
"build": "heft build --clean",
"clean": "heft clean",
"test": "heft test",
"test-only": "heft run --only test --",
"deploy": "heft dev-deploy",
"start": "heft start --clean",
"build-watch": "heft build --lite",
"package-solution": "heft package-solution",
"deploy-azure-storage": "heft deploy-azure-storage",
"eject-webpack": "heft eject-webpack",
"trust-dev-cert": "heft trust-dev-cert",
"untrust-dev-cert": "heft untrust-dev-cert"
}
}
heft configuration in spfx

Here’s how the old Gulp commands map to Heft:

Gulp commandHeft equivalent
gulp serveheft start
gulp buildheft build
gulp bundle --shipheft build --production
gulp package-solution --shipheft package-solution --production
gulp cleanheft clean

Read How to Change Solution Name in SPFx

Step 4: Add the SPFx Heft Rig

Heft uses a concept called rigs — shared build configurations that multiple projects can extend. This is what replaces the old sp-build-web rig from the Gulp days.

Create a new file at ./config/rig.json with this content:

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

This one file tells Heft: “use the SPFx web build rig for all the default build settings.” You don’t have to define TypeScript paths, Webpack entry points, or ESLint configs from scratch — the rig handles all of that for you.

Step 5: Replace the Sass Configuration

Open ./config/sass.json and replace everything in it with:

{
"$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft-sass-plugin.schema.json",
"extends": "@microsoft/spfx-web-build-rig/profiles/default/config/sass.json"
}
heft commands in spfx

This hooks your project’s Sass compilation into the Heft Sass plugin defined by the rig. If you had custom Sass settings in the old file (like useCSSModules or postProcessedFileExtensions), you can add those back here — they’ll override the rig’s defaults.

Step 6: Add the TypeScript Plugin Configuration

Create a new file at ./config/typescript.json:

{
"extends": "@microsoft/spfx-web-build-rig/profiles/default/config/typescript.json",
"staticAssetsToCopy": {
"fileExtensions": [".resx", ".jpg", ".png", ".woff", ".eot", ".ttf", ".svg", ".gif"],
"includeGlobs": ["webparts/*/loc/*.js"]
}
}
sharepoint framework gulp migration

The staticAssetsToCopy section tells Heft which non-TypeScript files to copy over during the build. This replaces what gulp copy-assets or similar custom tasks used to handle. Adjust the file extensions and globs to match whatever your project actually needs.

Check out How to Install NVM in Windows

Step 7: Update tsconfig.json

Replace the contents of your existing ./tsconfig.json with this:

{
"extends": "./node_modules/@microsoft/spfx-web-build-rig/profiles/default/tsconfig-base.json"
}

Your old tsconfig.json probably had a long list of compiler options. All of those are now inherited from the rig’s base config. You only need to add project-specific overrides here if you have them.

Step 8: Delete gulpfile.js

Just delete it.

rm gulpfile.js

If you had custom tasks in your gulpfile.js — like custom Webpack config, pre-build steps, or post-build file operations — don’t delete it yet. Keep it open in a separate window for reference while you set up the equivalent Heft plugins in the next section.

Step 9: Upgrade Your SPFx Production Dependencies

Update the core SPFx packages to v1.22:

npm install @microsoft/sp-component-base@1.22.1 @microsoft/sp-core-library@1.22.1 @microsoft/sp-lodash-subset@1.22.1 @microsoft/sp-office-ui-fabric-core@1.22.1 @microsoft/sp-property-pane@1.22.1 @microsoft/sp-webpart-base@1.22.1 --save-exact
upgrade spfx production dependencies

After making so many changes to packages, I’d strongly recommend doing a full clean reinstall:

# Windows (PowerShell)
Remove-Item -Recurse -Force node_modules
Remove-Item -Force package-lock.json

# Mac/Linux
rm -rf node_modules package-lock.json

# Then reinstall everything cleanly
npm install

This ensures your dependency tree is consistent and you’re not carrying over any stale Gulp-related packages.

Step 10: Test the Migration

Run a build to verify everything works:

npm run build

Or if you have Heft installed globally:

heft build --production

If the build completes without errors, you’re done with the core migration. Fire up the dev server with:

npm run start
# or
heft start --clean
microsoft spfx heft plugins

This will automatically open the workbench url. In case you are getting an error like in the image below.

Unable to load SPFx webpart after deploy

Just run the following command.

npm run trust-dev-cert
spfx failed to load component

Then, re-run the npm run start command; this time, without errors, you can get your web part as shown below.

migrating gulp packages to heft in sharepoint framework

Handling Custom gulpfile.js Tasks

This is where it gets more involved. If your old gulpfile.js was just the default SPFx boilerplate, you’re done. But if you had custom tasks, here’s how to handle the most common ones:

Custom Webpack Configuration

If you were using build.configureWebpack.mergeConfig() to inject custom Webpack settings, you have two options in Heft:

Option 1 — Use the webpack patch file (simpler):

Create a file at ./config/webpack.extend.js:

module.exports = function (existingConfig) {
existingConfig.resolve = existingConfig.resolve || {};
existingConfig.resolve.alias = {
...existingConfig.resolve.alias,
'@myAlias': require('path').resolve(__dirname, '../src/helpers')
};
return existingConfig;
};

Then reference it in your heft.json (more on that file below).

Option 2 — Eject Webpack entirely (for complex cases):

heft eject-webpack

This generates a full webpack.config.js in your project that you can modify directly. It’s the escape hatch for when you need complete control.

Custom Pre/Post Build Tasks

If you had build.rig.addPreBuildTask() or addPostBuildTask() For things like copying extra files or running scripts, use Heft’s run-script-plugin.

Create ./config/heft.json:

{
"$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft.schema.json",
"extends": "@microsoft/spfx-web-build-rig/profiles/default/config/heft.json",
"phasesByName": {
"build": {
"tasksByName": {
"my-custom-script": {
"taskPlugin": {
"pluginPackage": "@rushstack/heft",
"pluginName": "run-script-plugin",
"options": {
"scriptPath": "./scripts/my-custom-task.js"
}
}
}
}
}
}
}

Create ./scripts/my-custom-task.js and put your custom logic there. This script runs as part of the build phase.

Copying Files

The old build.copyStaticAssets type of operations now live in typescript.json under staticAssetsToCopy (which we already configured in Step 6). For more complex copy scenarios, use the copy-files-plugin in heft.json.

Common Issues and Fixes

A few things that tend to trip people up during migration:

  • ESLint errors after migration: Your old .eslintrc.js may reference @microsoft/eslint-config-spfx in a way that conflicts with the new package. Update the extends in your ESLint config to use @rushstack/eslint-config and re-run the build.
  • “Cannot find module” errors: Usually means stale node_modules. Do the clean reinstall from Step 9.
  • TypeScript errors you didn’t have before: If you upgraded to TypeScript v5.8, some stricter type checks may now flag issues that were silently ignored before. Fix them or stay on TypeScript v5.3 for now.
  • PnP SPFx Controls not working: If you use @pnp/spfx-controls-react, make sure you’re on a version that supports SPFx v1.22. Run npm ls @pnp/spfx-controls-react to check your current version and compare with their release notes.
  • Dev cert issues: If HTTPS fails on the local workbench, run heft trust-dev-cert to re-trust the certificate.

Using the M365 CLI to Generate an Upgrade Report (Optional but Helpful)

If you want a full list of every change needed for your specific project before you manually edit anything, the Microsoft 365 CLI can generate an upgrade report for you:

# Install M365 CLI if you don't have it
npm i -g @pnp/cli-microsoft365

# Generate the upgrade report
m365 spfx project upgrade --toVersion 1.22.0 --preview --output md > upgrade-report.md

Open upgrade-report.md — it will list every dependency that needs to change, every script to update, and any manual steps specific to your project. It’s a great way to audit before you start making changes.

What the Final Project Structure Looks Like

After migration, here’s what your key config files should look like:

your-spfx-project/
├── config/
│ ├── rig.json ← NEW (points to spfx-web-build-rig)
│ ├── heft.json ← NEW (only if you have custom tasks)
│ ├── sass.json ← UPDATED (now extends rig)
│ ├── typescript.json ← NEW (configures TS plugin)
│ └── package-solution.json (unchanged)
├── tsconfig.json ← UPDATED (now extends rig's base config)
├── package.json ← UPDATED (scripts use heft commands)
├── gulpfile.js ← DELETED
└── src/ (unchanged)
migrate from the gulp-based to the heft-based toolchain

Wrapping Up

In this tutorial, I explained how to migrate from Gulp based toolchain to Heft based toolchain in the SharePoint Framework (SPFx). Follow the above steps, and you should be able to migrate your project.

The key things to remember:

  • Uninstall the old Gulp packages and install the Heft equivalents
  • Add rig.json to point to @microsoft/spfx-web-build-rig
  • Update your config files (sass.json, typescript.json, tsconfig.json)
  • Replace your npm scripts with heft commands
  • Delete gulpfile.js (but migrate any custom tasks first)
  • Do a clean npm install at the end to flush out any stale dependencies

If you’ve got custom Gulp tasks, the translation to Heft plugins takes a bit of extra thought — but the run-script-plugin and copy-files-plugin cover most real-world scenarios.

Also, you may like:

Live Webinar

Build an IT Help Desk App using Power Apps and Power Automate

Join this free live session and learn how to build a fully functional IT Help Desk application using Power Apps and Power Automate—step by step.

📅 29th Apr 2026 – 10:00 AM EST | 7:30 PM IST

Download User registration canvas app

DOWNLOAD USER REGISTRATION POWER APPS CANVAS APP

Download a fully functional Power Apps Canvas App (with Power Automate): User Registration App

Power Platform Tutorial

FREE Power Platform Tutorial PDF

Download 135+ Pages FREE PDF on Microsoft Power Platform Tutorial. Learn Now…