Article
4 comments

How to version new SharePoint Framework projects

Project versioning as we used to know it was not a big challenge. Not as long as you only used Visual Studio.
The thing is that assigning a proper version of your SharePoint Framework project is more tricky than simply apply a single version to it. There are more than one version of your project, that doesn’t match and have different purposes.

Visual Studio project version

Visual Studio projects use a version number for each project that contains four digits. This kind of is available everywhere in the Microsoft Universe. Every SharePoint project in the past used this version.
The version contains of four numbers and follows the pattern Major, Minor, Build and the last digit is the revision number.

Visual Studio Version

Visual Studio Version

When you upload the output of a SharePoint Framework project this the app file need to contain a valid version number. The lowest possible version is ‘1.0.0.0’. If a version number below the first major build will be used. SharePoint automatically uses the version ‘1.0.0.0’. No matter if you have specified the version ‘0.9.0.0’.

NodeJS project version

When you create a new project using the yeoman generator you get in the root folder, the ‘package.json’. This file contains another version number that is incompatible with version number used in Visual Studio Projects.
The concept to assign version numbers is called semantic versioning or short ‘semver’.

Semantic Versioning

Semantic Versioning

A valid, semantic version number only contains three mandatory parts. The major, minor and the patch number instead of ‘Build’. Optional, additional labels can be assigned to the version number delimited by a dash. Common values for labels are ‘alpha’, ‘beta’, ‘rc’ for release candidates. Sounds good, because it’s less cryptic than the Microsoft version.

SPFX versioning issue

In fact, any SharePoint Framework project has two different kinds of versions. The more project oriented version number is stored in the ‘package.json’. The web part related is stored in the ‘package-solution.json’ inside the config folder.
Both are valid versions of your project, but they are not in sync and needs to be updated individually. For SharePoint you can update the package-solution file. For the overall project you update the ‘package.json’ in the root folder.
Sooner or later you will lose track of your versions and it will be hard to decide which the correct one is.

Tool support for npm / NodeJS versioning

The node package manager is not only capable to install node modules. It helps you to set a proper version in your ‘package.json’. To update the version you simply need to execute the following command.

npm version <major|minor|patch>

So when you like to increment the major version simply execute ‘npm version major’, use minor instead of major to update to a minor version. In case you like to patch the web part simply specify ‘npm version patch’.

Update version to next patch version

Update version to next patch version

Voilá. The version in the ‘package.json’ has been updated.

Sync npm version with your web part version

Currently there is no tooling support available that allows you to update the version of your web part solution file. You can update the version number manually by editing the ‘package-solution.json’.
Updating this version is not something I like to do all the time. The question is, is there a better way to do this?
Lets say I like to use the tool driven project version of my main project directly in my web part code too.
To solve this issue only a simple gulp task is required. There is one last thing we need to manage. The incompatible version numbers.

Create matching version numbers

As mentioned previously, we need to find a way to make both version numbers matching. So we need to assign the three parts of the npm package version to the SharePoint solution version number.
To create a proper package solution version four digits are needed, but npm contains only of three individual digits.
Let me give you an example. The current overall project version is set to ‘1.9.1-beta’. Now the only thing that needs to be done is to remove the label from the version number. The delimiter to identify the label is a simple dash. So we split the version string and use only the first part.
So we get a new partial version number ‘1.9.1’. The last thing that needs to be done is to add the string ‘.0’ to the partial version number. This way we get the version ‘1.9.1.0’, a valid web part app version of SharePoint.
From a Microsoft version perspective, we lose the last part, the revision number. I think this loss is bearable.

Gulp task to sync versions

The easiest way to implement the version sync is to write a custom gulp task. The first thing that needs to be done is to read both configuration files. Then get the version from the ‘package.json’, create a proper new matching version and write this new version number to the configuration file stored in the ‘package-solution.json’ file.

'use strict';

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

build.initialize(gulp);

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

  // import gulp utilits 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));

});

Now only the version of the npm package needs to be updated through ‘npm version’. After the version has been changed simply execute ‘gulp version-sync’.

Sync version automatically

Running the gulp task manually is nice, but there is a better way to do this. Through the help of a simple npm script.
Whenever you update your version two events will be raised. ‘preversion’ will be raised before the version will be updated. ‘postversion’ is the right event to use. This will be raised after the version have been changed. Simply add a new script to your ‘package.json’. Name the script ‘postversion’ and define the execution with ‘gulp version-sync’.

  ...
  "scripts": {
    "build": "gulp bundle",
    "clean": "gulp nuke",
    "test": "gulp test",
    "postversion": "gulp version-sync"
  }
  ...

Finally, lets put this to test. Simply execute ‘npm version’. Now the version in the ‘package.json’ will be updated first. The version sync task will be automatically called and finally we get a version corresponding to our ‘package-solution. json’.

Automatic update of version

Automatic update of version

SPFx versioning issue solved?

I would say yes. At least it helps to manage the centralized version. I know it is just an intermediate fix to make the different version schematics matching.
It would be great if SharePoint would support semantic version in addition but by now we need to use this workaround.
What do you think? Will you use this centralized version or will you just update one or the other version identifier.

4 Comments

  1. Would the Solution version nr (semver) also be useful to write to (all) the webpart manifest files?

    // process webpart manifests too
    gulp.src(‘./src/webparts/*/*.manifest.json’).pipe(tap(function(file,f){
    // load the webpart manifest
    var wpManifest = require(file.path);
    // update the version nr of the webpart manifest
    wpManifest.version = pkgConfig.version;
    // log the new version
    gutil.log(‘New Manifest Version ‘ + wpManifest.alias + ‘ t’ +pkgConfig.version);
    // write changed webpart manifest file
    fs.writeFile(file.path, JSON.stringify(wpManifest, null, 4));
    }));

    Reply

Leave a Reply

Required fields are marked *.


This site uses Akismet to reduce spam. Learn how your comment data is processed.