A few years ago, React introduced the React Profiler to React v16.5 in the React DevTools plugin available for Chromium browsers (Chrome & CrEdge) and Firefox.
Developers can use the Profiler API to collect timing information about each component that’s rendered in order to identify performance bottlenecks in React applications.
For those of us creating React apps in SharePoint Framework (SPFx) solutions, this is a great resource for building well performing apps for your customers!
Cool right?
SPFx? Not so fast my friend…
Sure… it’s cool… but when you try to use it, you get hit with the following error:
What’s going on?
The error message indicates that we need React v16.5 or higher. SPFx projects haven’t used an older version of React since SPFx v1.7.1.
So, if we’re using a relatively modern version of SPFx (anything v1.8+) it should work, but it isn’t… why?
The issue with SPFx projects
As the error indicates, for the profiler to work, it needs either a development or production-profiling build.
The reason you’re getting this is because the profiler needs React to be present in the bundle of your project. By default, all SPFx projects exclude React from your generated bundles & instead, assume they’re already on the page as external references.
Furthermore, the profiler it needs a special profiling build, or a development build.
Understanding how SPFx bundles are generated
Before I share the solution, let’s recap how SPFx works.
The SPFx uses webpack to generate the bundles used to load our SPFx components. The build toolchain dynamically creates the webpack config when you run gulp bundle. The generated webpack configuration instructs webpack to always exclude the npm packages react & react-dom from your generated bundle.
Why? The SPFx assumes that React is already on the page, a safe assumption because SharePoint Online uses React in their components. Regardless, every SPFx project that uses React will automatically exclude these two npm packages so we don’t have to go through the process of excluding it ourselves in every project’s ./config/config.json file using the externals
element.
I cover both of these topics in two chapters of my Mastering the SharePoint Framework Ultimate course bundle.
You’ll learn how to generate sourcemaps, include them in your deployed packages, compile Markdown files to HTML, and many more tricks!
This means we have two things we need to do to enable the React DevTools profiler:
- Add React to the generated bundle
- Ensure the React version included in the bundle is a profiler friendly version
Ideally, we only want this to happen in development, never in production, because it has a significant impact on our bundles. For example, the bundle in my test projects without these changes is ~62 KB (19KB if minified in a production build). However, once I make the following changes the bundle will balloon to 1.1MB. Clearly this is only something you want to do in development, not production.
Thankfully we can solve these two issues easily just with just a few extra lines of code in our project’s ./gulpfile.js.
Fix #1: Include React in the generated bundle
Let’s first put the two npm packages back in the bundle. To do this, we need to tell webpack to not exclude them from the bundle generation.
In your project’s ./gulpfile.js, add the following code to the end of the file:
build.configureWebpack.mergeConfig({
additionalConfiguration: (wpcfg) => {
// if dev build, mod config for profiling react
if (wpcfg.mode === 'development') {
// remove externalization of react & react-dom
wpcfg.externals = wpcfg.externals.filter((external) => {
return ((external !== 'react') && (external !== 'react-dom'));
});
}
return wpcfg;
}
});
This code takes the configuration generated by the SPFx build toolchain and checks if we’re currently in a development
build. This is true when we run gulp serve or gulp bundle without any arguments.
Then, we look at the collection of externals
defined in the config and removes references to react
and react-dom
. Now, when webpack runs & comes across a reference to either of these two packages, it will include them in the generated bundle
Fix #2: Swap out React with a React profiler bundle
The second fix is to configure webpack to use the profiler friendly package of React when it imports it into the bundle. This is done using the webpack resolve configuration. This option lets us configure how modules are resolved.
To implement this, add the following code to your project’s ./gulpfile.js within the if
statement you just added above:
// add alias for the react-dom profiler
wpcfg.resolve.alias = {
'react-dom$': 'react-dom/profiling'
};
This tells webpack to include the module react-dom/profiling in the bundle when it comes across import
statement with an exact match for react-dom
.
Review & test the solution
To recap, in order to use the React DevTools profiler in SPFx projects, add the following code to add support for profiling React projects to the end of your ./gulpfile.js:
build.configureWebpack.mergeConfig({
additionalConfiguration: (wpcfg) => {
// if dev build, mod config for profiling react
if (wpcfg.mode === 'development') {
// add alias for the react-dom profiler
wpcfg.resolve.alias = {
'react-dom$': 'react-dom/profiling'
};
// remove externalization of react & react-dom
wpcfg.externals = wpcfg.externals.filter((external) => {
return ((external !== 'react') && (external !== 'react-dom'));
});
}
return wpcfg;
}
});
Now, run gulp serve and load your SPFx React component in the SharePoint workbench. You can now run the profiler in the dev tools: