Optimize your SharePoint SPFx package load times

Laurence Do
4 min readMar 2, 2021

Users expect websites to be blazing fast, and shaving a couple seconds off your initial page load time can be the difference between a slick or sluggish feeling user experience. Luckily, many bundle optimization tools and techniques such as lazy loading and dynamic imports can also be brought to bear in SPFx solutions.

Analyze package contents

The first step is identifying the opportunities for optimization. Bundle Analyzer allows us to visualize the size of each dependency in a package with an interactive treemap. This helps us understand what exactly is in our package and start to look for opportunities to optimize.

Refer to this Microsoft documentation to set up Bundle Analyzer for your SPFx solution with a couple simple steps. Those steps are also replicated at the end of this article for reference.

Cutting out the fluff

What are the biggest modules? Are there any unnecessary modules in there?

Swap out big libraries

Evaluate your large modules and consider, can any be replaced by smaller libraries that can get the job done?

For example, while Ajv is one of the go-to libraries for validating JSON schemas, there are other libraries for JSON validation with less than one-fifth of the package size. If your use case is simple, those may work just fine!

Eliminate unused modules

When leveraging libraries with many components or functions, make sure that only the specific dependencies being used are pulled into the package, rather than the entire library.

Tree shaking eliminates “dead code” and ensures that unused modules don’t get pulled into our package, and the SPFx build process will perform tree shaking when possible. For libraries that support tree shaking, we don’t have to worry about unnecessary modules being pulled in.

However, many libraries like lodash do not. These are the ones we have to pay attention to how we import. For example, the following will include the entire lodash library into the package:

import {filter} from "lodash";

Whereas this will import the considerably smaller filter module:

import filter from “lodash/filter”;

Bundlephobia.com is an easy way to tell whether a library supports tree shaking. Those that do will have a tree-shakable label.

Lazy loading

Are there big modules that are only used in components not in the critical path for users? If so, consider lazy loading them.

As a real-world example, I recently built a webpart with a modal popup which relied on some big libraries to provide drag and drop functionality. Nothing else in the webpart required those libraries, and the vast majority of the time the modal won’t be opened. That is a prime candidate for lazy loading!

Let’s walk through this simple example with a BigComponent that’s only shown after the user clicks a button:

Now, let’s lazy load BigComponent so that it and its dependencies are only loaded after the button is clicked!

First we’ll remove the import from the top of the file:

// import { BigComponent } from "./BigComponent";

Then, add a new state variable to store the module to be dynamically imported:

const [bigModule, setBigModule] =
React.useState<typeof import("./BigComponent")>(null);

When the button is clicked, we will import BigComponent and save it to the bigModule state variable. Note that the import is awaited, as it is an asynchronous operation.

Also note the webpackChunkName magic comment, which instructs Webpack how to name the chunk file.

const module = await import(
/* webpackChunkName: "big-component" */
"./BigComponent"
);
setBigModule(module);

Finally we can render it just like any other React component!

<bigModule.BigComponent />

Now after the solution is rebuilt, in the /dist folder there should be separate chunk files for Big Component:

And those chunk files will only be loaded in the browser when the button is clicked:

Here is the complete code example with lazy loading:

Setting up Bundle Analyzer

To set up Bundle Analyzer to work with the SPFx solution, install the analyzer library:

npm install webpack-bundle-analyzer --save-dev

Add the following into gulpfile.js for your project:

After running gulp bundle, the bundle analysis treemap report will be added to the temp/stats folder.

--

--