M365Bass.github.io

Package versioning in SPFx solutions

Recently, I’ve been working on releasing a few SPFx components for an Intranet project I’m working on. Given how SharePoint automatically handles updating SPFx components when a new version is available, it made sense to automate versioning rather than changing a version number in three different files with every release.

A quick Google search took me to an old gem from Stefan Bauer as well as a more recent adaptation from Hugo Bernier - I needed a bit of both to achieve what I want.

By default, NPM includes npm version which bumps the version in both package.json (and package-lock.json if you have one) using npm version major|minor|patch. However, SPFx relies on the version number in package-solution.json. The code below syncs both.

It is two-part: The main bit uses a gulp task to create a version-sync task which updates the SPFx version to match the NPM package version. The other part is an NPM task to run the version-sync gulp task every time the NPM package version is updated. There’s a postversion event that’s triggered every time npm version is run so it seemed like the right place for it. Depending on project structure, NPM may decide not to create a commit for npm version (but it does when you have the package file at the top level of the repo) so the last bit of the postversion should change to reflect that.

Use this one when package file not at the top level of the solution (typically, multiple solutions in same repo)

"postversion": "gulp version-sync && git add . && git commit -m \"auto-versioning\""

Use this one when package file not at the top level of the solution (one solution generating one package hence a single package file at the top level)

"postversion": "gulp version-sync && git add . && git commit --amend --no-edit"

This is what the final gulp file looks like (SPFx 1.12.1)

'use strict';

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

build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);

var getTasks = build.rig.getTasks;
build.rig.getTasks = function () {
  var result = getTasks.call(build.rig);

  result.set('serve', result.get('serve-deprecated'));

  return result;
};

build.initialize(require('gulp'));

gulp.task('version-sync', async function () {

  // import gulp utilities to write error messages
  const gutil = require('gulp-util');

  // import file system utilities form nodeJS
  const fs = require('fs');

  // read package.json
  var pkgConfig = require('./package.json');

  // read configuration of web part solution file
  var pkgSolution = require('./config/package-solution.json');

  // log old version
  gutil.log('Old Version:\t' + pkgSolution.solution.version);

  // Generate new MS compliant version number
  var newVersionNumber = pkgConfig.version.split('-')[0] + '.0';

  // assign newly generated version number to web part version
  pkgSolution.solution.version = newVersionNumber;

  // log new version
  gutil.log('New Version:\t' + pkgSolution.solution.version);

  // write changed package-solution file
  fs.writeFile('./config/package-solution.json', JSON.stringify(pkgSolution, null, 4), () => { });

});
TAGS