Improve SharePoint Framework Build Times by hacking Gulp and Webpack

Improve SharePoint Framework Build Times by hacking Gulp and Webpack

SharePoint Framework (SpFx) is the latest-and-greatest way to build web parts and bolt on modifications to SharePoint Online (SpFx also has a limited on-premises capability with SharePoint 2016).

Adopting SpFx has been mostly a positive experience but as with any new technology there are challenges and growing pains. One challenge specifically is creeping build times for our core project. As web parts, extensions and core libraries are added, it takes longer to build the project.


Scientific MS Paint depiction of SpFx build times per number of elements in the project

As you can see in the graph, approaching 30 elements in the SpFx project, builds can take over 60 seconds to complete*. Development disruptions like this are one of the reasons developing web parts the old way with Visual Studio and C# code was so maddening!

As a general disclaimer this is a complete hack, but for my project it reduced build time by over 80%

Everything I will go over below I have committed to git for reference at https://github.com/pdemro/spfx-gulpfile-hack

*Build times estimated using Windows 10. Linux generally builds SpFx projects faster, but the growth for build time is still in play as additional components are added.

Speed up SpFx Build Times

The general idea is to tell SpFx's gulp-core-build-typescript to compile only the necessary typescript files rather than the whole project. I'll also show how to hack the SpFx config.json file to reduce the load on webpack for each build.

vroom

Quattro by Lewis Taylor / CC BY-NC 2.0

In this exercise you will update gulpfile.js, config.js and the source code for gulp-core-build-typescript which should help speed up performance for large SpFx projects.

Step one: Run a full build

Run gulp build or gulp serve --nobrowser without making any modifications. This will populate the /lib folder with build outputs from the whole project. Once you've completed these steps, the TypeScript transpiler will only overwrite components in /lib which you define and the rest will stay the same

If you delete /lib /dist or run gulp clean, you will need to re-run the full build.

gulpfile.js

Gulp is the module which manages transpiling and building the SpFx project. By modifying gulpfile.js you can adjust how the framework builds the project.

I added my gulpfile.js updates to a separate file to make the updates easy to roll-back for full builds, and to avoid breaking the build when committing to Git. To load a separate file into gulpfile.js:

try {
    require('./gulpfile.custom');
} catch (e) {
    if (e.code !== 'MODULE_NOT_FOUND') {
        throw e;
    }
}

gulpfile.custom.js

gulpfile.custom.js is where I put a majority of the build updates. First include @microsoft/sp-build-web

const build = require('@microsoft/sp-build-web');

Next, disable tslint to save a few precious seconds

build.tslint.enabled = false;

TypeScript is one of the primary offenders in an SpFx project when it comes to long build times. To speed things up, tell it to build only the files it needs

build.typescript.replaceConfig({
    sourceMatch: [
        //Your webpart files & supporting files
        "src/**/<your webpart here>/**/*.ts",
        "src/**/<your webpart here>/**/*.tsx",
        //Default settings
        "typings/main/**/*.ts",
        "typings/main.d.ts",
        "typings/tsd.d.ts",
        "typings/index.d.ts"
    ],
    failBuildOnErrors: false
});

If you still want to include TSLint in the build, you can use this same method to reduce the number of files it has to process

build.tslint.mergeConfig({
    sourceMatch: [
        "src/webparts/<your webpart here>/**/*.ts",
        "src/webparts/<your webpart here>/**/*.tsx",
    ]
});

gulp-core-build-typescript source code

If you try to build the project now you're going to get an error message like 'Do not use mergeConfig with gulp-core-build-typescript'. Solution is to simply remove this exception from the gulp-core-build-typscript source code.

The file should be located at

<spfx project path>/node_modules/@microsoft/gulp-core-build-typescript/lib/TypeScriptTask.js

Comment out the lines

/** Override the new mergeConfig API */
TypeScriptTask.prototype.mergeConfig = function (config) {
    throw 'Do not use mergeConfig with gulp-core-build-typescript';
};

I don't have an explanation for why they hard-coded this exception. If I find out I will update.

config.json

Your project should already be building significantly faster after reducing the TypeScript workload. You can speed things up further by telling webpack only to update the bundle for the webpart currently being worked on. This is done by removing all other components in /config/config.json. In my sample project, I have three web parts and two extensions, but have cut away at my config.json until only the current web part remains:

{
  "$schema": "https://dev.office.com/json-schemas/spfx-build/config.2.0.schema.json",
  "version": "2.0",
  "bundles": {
    "hello-world-2-web-part": {
      "components": [
        {
          "entrypoint": "./lib/webparts/helloWorld2/HelloWorld2WebPart.js",
          "manifest": "./src/webparts/helloWorld2/HelloWorld2WebPart.manifest.json"
        }
      ]
    }
  },
  "externals": {},
  "localizedResources": {
    "HelloWorld2WebPartStrings": "lib/webparts/helloWorld2/loc/{locale}.js",
  }
}

This might be better illustrated in my sample project via this commit. I find it useful to keep a backup of config.json (I called it config.full.json in the sample project).

Build and Serve the Project

After all this preparation you should be ready to start hosting the code and work with the SharePoint workbench.aspx

gulp serve --nobrowser

Gotchas and Limitations

If you've made it this far it is probably clear to you that this is not an ideal solution. However if you are working with a large project with dozens of SpFx components and dozens or even hundreds of typescript files, this has been a life saver.

A few gotchas off the top of my head

  • This should only be used while in development of specific modules. This will not help performance when doing a full build
  • A fresh npm install will blow away the hack to gulp-core-build-typescript.
  • Make sure to revert this mess before merging into a collaborative branch or risk breaking the build
  • As mentioned, gulp clean or removing the /lib or /dist folders will require a full build of the project

Summary

If you are managing a large SpFx project and have other tips or tricks to improve build time please let me know! Otherwise I hope this was able to help.

Make sure to check out the GitHub project for this article at https://github.com/pdemro/spfx-gulpfile-hack

SpFx build takes forever; sharepoint framework long build time; takes forever to build; SpFx build is slow; SpFx slow build