From Gulp to Heft: Webpack Config in SPFx 1.22+
You followed the Microsoft instructions to upgrade from Gulp to Heft. During this upgrade, you found some Webpack configuration that also needs to be migrated. It is a single configuration required only for this project. Let me explain what you can do and when to do it.
TL;DR: SPFx Webpack Customization Approaches
There are actually three ways to modify the Webpack configuration.
- Heft Webpack Patches – Reusable npm packages, complex plugins (bundle analyzer, external tools)
- spfx-customize-webpack.js – Project-specific config, easy migration from Gulp, standard Webpack rules
- webpack-eject: Full control, custom build pipeline, advanced scenarios (breaks SPFx updates)
I looked just at the first two options since the last one has way higher complexity.
Option 1: Heft Webpack Patch in SPFx 1.22 and beyond
In my article about how to make WebAssembly work in the SharePoint Framework 1.22 and beyond, I used this approach.
The main purpose of webpack patches is for reusability. As noted in the documentation, the Webpack bundle analyzer is a great example of this.
You create an npm package first.

You create a file that tells Webpack how to customise.

Once you publish this package, you have a perfect reusable Webpack configuration for all of your projects.
The last step is to reference the package in the webpack-patch.json configuration in the config folder.
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/spfx-build/webpack-patch.schema.json",
"patchFiles": [
"./node_modules/heft-patch/src/heft-wp-bundle-analyser.js"
]
}
And with that, you have a perfectly fine reusable package just for these configurations.
Option 2: Project-Specific Webpack configuration
Another option for the Gulp to Heft migration is to have a project specific configuration. In most projects and cases, you might have an on-off configuration you like to apply specifically for your project. WebAssembly is a great example of that. I might need it in my current project, but nowhere else.
For such configurations, all that is needed is to create a spfx-customize-webpack.js file in the configuration directory. The Heft build chain looks up this by default if such a file exists and includes its contents in the webpack configuration.
/**
* SPFx Webpack Customization - WebAssembly Support
* Automatically discovered by @microsoft/spfx-heft-plugins
*/
module.exports = function(webpackConfig, taskSession, heftConfiguration, webpack) {
webpackConfig.module.rules.push({
test: /\.wasm$/,
type: 'webassembly/async',
});
webpackConfig.experiments = {
asyncWebAssembly: true,
}
};
Compared to the original gulp file, it almost looks identical.
'use strict';
const build = require('@microsoft/sp-build-web');
// WebAssembly configuration
build.configureWebpack.mergeConfig({
additionalConfiguration: (generatedConfiguration) => {
generatedConfiguration.module.rules.push({
test: /\.wasm$/,
type: 'webassembly/async',
});
generatedConfiguration.experiments = {
asyncWebAssembly: true,
}
return generatedConfiguration;
}
});
build.initialize(require('gulp'));
Key Differences: SPFx Webpack Configuration Migration (Gulp → Heft)
Gulp used this in the gulpfile.js:
// gulpfile.js (root level)
build.configureWebpack.mergeConfig({
// configuration here
});
In Heft, you have to use the following:
// config/spfx-customize-webpack.js (dedicated file)
module.exports = function(webpackConfig, taskSession, heftConfiguration, webpack) {
// configuration here
};
API Pattern Pattern & Function Signatures
Of course, with a new build chain, the API has slightly changed.
The Gulp approach used the following to merge the configuration.
build.configureWebpack.mergeConfig({
additionalConfiguration: (generatedConfiguration) => {
// Modify generatedConfiguration
return generatedConfiguration;
}
});
In Heft, you can modify the Webpack configuration directly without ejecting.
module.exports = function(webpackConfig, taskSession, heftConfiguration, webpack) {
// Modify webpackConfig directly
// No return needed
};
Key improvements
To apply the configuration change this way comes with many great benefits. It uses autodiscovery and simply removing this file will bring SharePoint Framework back to its original state. This is true for the Webpack Patch, too, of course. Other benefits include a simpler API that allows direct modification of the configuration, rather than the callback pattern, and provides better context.
This approach is an easier, more applicable way for many developers, and the most straightforward way to migrate from Gulp to Heft. I will make the transition smoother and less stressful.
Summary
As you can see in the screenshot, both scenarios work well together in a single solution.

The second option works because it is part of the @rustack/heft-webpack5-plugin. It is the foundation for @microsoft/spfx-heft-plugins, which provides the auto-discovery functionality of spfx-customize-webpack.js.
Webpack patches are ideal for reusable configurations, while the second option is better for simple, one-off tweaks.
As I mentioned in my previous blog post, where I upgrade SPFx using AI, documentation for the new Heft toolchain, especially for SPFx, still has room to improve. Clearer guidance on when to choose each approach would help you feel more confident and supported in your migration decisions.
The option I showed with ‘spfx-customize-webpack.js’ has been completely forgotten to document.
I tested it on a real project that I upgraded to 1.22.1, and it works perfectly.
In one of the upcoming blog posts, I will cover how to apply multiple webpack patches in a single package.
Further readings
- Customize SPFx Heft Toolchain: Plugins, Script, Webpack, by Andrew Connell, provides a great overview of the new terms and practical examples
- SPFx Framework Toolchain and Webpack – Features the Webpack bundle analyzer example that I modified and fixed to make it reusable.