Article
0 comment

‘gulp dist’ in SPFx? One command to create a clean solution package

Many projects that use gulp as the build system mostly implement a particular gulp task that is name ‘dist’ for distribution. This task package and bundle everything for production use.

Can we have a gulp task like this in SPFx too? Yes, we can have this too. First, let us take a look at the steps you need to do when you like to create a clean ‘sppkg’ file in the SharePoint Framework.

Build a clean package

The steps to build a clean package are:

  1. gulp clean – removes all files from previous builds
  2. gulp bundle – creates a new build and writes manifest to the temp folder
  3. gulp package-solution – creates the ‘sppkg’ file

The ‘build’ task is not required because ‘bundle’ runs a build by default. The solution file created after these three tasks is a debug or development package that references the local workbench still.

To create a package for production the ‘–ship’ or ‘–production’ are required parameters.

On task that does that all

In Gulp, you can create a new task that relies on other existing tasks. You can define other tasks as so-called dependencies that need to run first.

gulp.task('dist', ['clean', 'bundle', 'package-solution'], () => {
   // do nothing in here or additional steps
})

The first argument is the name of the task. In this case ‘dist’. The second argument defines the order of dependent gulp tasks. In other words, it first cleans everything up, executes bundle and then creates a package for the solution for us. The mission is accomplishing right? Well not so fast.

Problem when executing the gulp task this way.

When you execute the task like this, you get some error messages. The reason for this is that some subtasks get called by clean, bundle or package-solution, and this causes this trouble. It is not a problem of the build rig created by Microsoft around the SPFx task. It is a problem with the current gulp version (3.9.1) the SharePoint Framework uses.

If SPFx uses gulp version 4.0.0 someday, the problem is easy to solve because this version has a way better handling if tasks should run parallel or serial.

gulp.task('dist', gulp.series('clean', 'bundle', 'package-solution'), () => {
   // do nothing in here or additional steps
})

Passing the gulp tasks inside ‘gulp.series’ does the trick there and make sure that one task gets executed after another. (Gulp 4 – new task execution)

Solve this issue in Gulp 3.9.1

This issue is not specific to the SharePoint framework. It is more a general problem with task handling in older versions of gulp. To solve it someone wrote a gulp plugin named ‘gulp-sequence‘ that does the trick.

The first step is to install this npm package to your project.

npm install gulp-sequence --save-dev

The second step is to reference this package in the gulp file and this reference right after ‘gulp’ and ‘sp-build-web’.

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

The third step is to modify the gulp task to use the gulp sequence.

gulp.task('dist', gulpSequence('clean', 'bundle', 'package-solution'), () => {
   // do nothing in here or additional steps
});

Now everything is was executed in the right way, and the result is a new clean ‘sppkg’ file. The build target is still ‘DEBUG’ instead of production. You can still pass in the ‘–ship’ or ‘–production’ options which creates a package ready to ship to your customer.

SPFx package after running the dist gulp task

SPFx package after running the dist gulp task

Always ship on ‘gulp dist’

It would make sense to use this distribution task only for production releases. This way you don’t have to think about additional parameters like ‘–ship’ or ‘–production’. NodeJS stores all command line arguments in the ‘process’ variable named and a property named ‘argv’. If it should automatically use the ‘–ship’ argument too, we need to add it to the collection of arguments.

'use strict';
// check if gulp dist was called
if(process.argv.indexOf('dist') !== -1){

  // add ship options to command call
  process.argv.push('--ship');

}

The first thing is to check if ‘dist’ was set on the arguments because we won’t have the ‘–ship’ option used all the time. ‘argv’ stores everything in an array to we need to push it just in. Finally, we have new gulp task that combines all required step in one single command.

See it live in action