SharePoint Framework, webpack 4 and tree shaking

In August 2019 SharePoint Framework 1.9.x was released. Among different changes also support for Webpack 4 was introduced. What does it mean for us? It means slightly improved build speed, support for a wide range of plugins and better tree-shaking. 

What is webpack tree-shaking exactly? In simple words, webpack is smart enough to automatically remove "dead modules" (in other words unused code/modules) from your resulting bundle. It reduces the size of the resulting bundle, thus improves load performance.

Tree shaking with SharePoint Framework

We can leverage tree shaking features in SharePoint Framework as well. For example, if you use Office UI Fabric React in your code, most likely you use below code to create a button (for SharePoint Framework version less than 1.9.x, react based): 

import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';
....
return (
      <div>
        <PrimaryButton>hello</PrimaryButton>
      </div>
    );

Take a note on import statement. It's very important that we import from 'office-ui-fabric-react/lib/Button' and not from 'office-ui-fabric-react'. In the latter case, we include the whole fabric react sources into our bundle (including sources for other controls we probably don't need), which drastically increases the bundle size. That's why the recommendation was to include only the needed components: 

import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';

However, starting from version 1.9.x of SharePoint Framework we can just import from "root" module avoiding any bundle size issues (as you guessed thankfully to webpack tree-shaking):

import { PrimaryButton } from 'office-ui-fabric-react';

Having below very simple component

export default class HelloWorld extends React.Component<IHelloWorldProps, {}> {
  public render(): React.ReactElement<IHelloWorldProps> {
    return (
      <div>
        <PrimaryButton>hello</PrimaryButton>
      </div>
    );
  }
}

let's compare the resulting bundle size for different SharePoint Framework versions and different import styles (using command gulp bundle --ship, because tree-shaking works only for production builds): 

SPFx version/bundle size import { PrimaryButton } from 'office-ui-fabric-react/lib/Button'; import { PrimaryButton } from 'office-ui-fabric-react';
1.9.1 (webpack 4) 168KB 168KB
1.8.2 (webpack 3) 182KB 838KB

 

So now you see, that even if we use "full" import with SPFx 1.9+, webpack removes all unused modules and the resulting bundle size remains untouched. 

Important! Tree shaking doesn't work for all external dependencies. It only works for those, which support tree shaking (i.e. they use javascript module system). Office UI Fabric React supports it (version 6.x+). On the other hand, the popular lodash module doesn't support tree shaking by default (at least inside SharePoint Framework based solution).

Checkout below comparison table for lodash (and lodash-es):

SPFx version/bundle size import { escape } from "lodash"; import { escape } from "lodash-es";
1.9.1 (webpack 4) 74KB 4KB
1.8.2 (webpack 3) 75KB 92KB

 

What is "lodash-es"? That's a special version of lodash, which is based on javascript modules. As you can see from the above table, it's subject to tree shaking and the bundle size is significantly smaller for SPFx 1.9+. Don't want to care about specific imports from lodash? Then just use SPFx 1.9+ and lodash-es package!

HINT!

You can use service bundlephobia (btw a very handy tool to check bundle sizes for libraries) to check if any particular npm package supports tree shaking. Check out the green icon in the bottom:

Conclusion

SharePoint Framework 1.9+ has built-in support for webpack 4. It allows us to write a bit cleaner code with automatic removal of dead or unused modules. Keep in mind, that this cool feature only works for libraries, which were written using ECMAScript modules syntax. Thus it works for Office UI Fabric React and lodash-es libraries. As usual, the rule of thumb is to always follow general production optimization rules (use CDN for the third party if possible, analyze bundle size, etc.).

Title image credits - FreeVector.com