Jun 17, 2018

Issues with SPFx packages version

Hi SharePoint developers,

In this quick post, I would like to highlight something I encountered recently that might help while working on SPFx projects.

The issue

A few days ago, an issue has been posted by Ashley on the sp-dev-solutions GitHub repository here where the Site Designs Solutions is maintained. When she cloned the repo, installed the dependencies running npm install and tried to execute the solution, she got an issue. The issue happened to be a very strange one:

error TS2345: Argument of type 'ServiceScope' is not assignable to parameter of type 'ServiceScope'.

As you can see, the type ServiceScope is not recognized as being the same type as ServiceScope... Well, that sounds weird... Obviously, I didn't encounter this one on my original local repo, but got it when I clone it as a new local one. Moreover, there has been no changes in the involved code for a while, at that happened all of a sudden !

What happened ?

Actually, what happened in the last days was the release of SPFx 1.5 ! Ok that must be it ! Something must be messed up with the packages versions, I then take a look at the package.json file of my project.

The package versions

Actually, all the package versions were 1.4.1.

{
    "name": "site-designs-studio",
    "version": "1.1.0",
    "private": true,
    "engines": {
        "node": ">=0.10.0"
    },
    "scripts": {
        "build": "gulp bundle",
        "clean": "gulp clean",
        "test": "gulp test"
    },
    "dependencies": {
        "react": "15.6.2",
        "react-dom": "15.6.2",
        "@types/react": "15.6.6",
        "@types/react-dom": "15.5.6",
        "@microsoft/sp-core-library": "~1.4.1",
        "@microsoft/sp-webpart-base": "~1.4.1",
        "@microsoft/sp-lodash-subset": "~1.4.1",
        "@microsoft/sp-office-ui-fabric-core": "~1.4.1",
        "@microsoft/sp-dialog": "^1.4.1",
        "@types/webpack-env": ">=1.12.1 <1.14.0",
        "ajv": "~5.2.2",
        "react-sortable-hoc": "^0.6.8"
    },
    "devDependencies": {
        "@microsoft/sp-build-web": "~1.4.1",
        "@microsoft/sp-module-interfaces": "~1.4.1",
        "@microsoft/sp-webpart-workbench": "~1.4.1",
        "gulp": "~3.9.1",
        "@types/chai": ">=3.4.34 <3.6.0",
        "@types/mocha": ">=2.2.33 <2.6.0",
        "ajv": "~5.2.2"
    }
}

So, at first sight, no issue there... Except maybe if you carefully look at line 22, the sp-dialog dependency is set to ^1.4.1. What does that caret mean? According to the NPM Semver docs, it will take the latest available version for the most-left non-zero digit, in other words, with the current versioning base of SPFx, and the recent release of SPFx 1.5, the dependency version ^1.4.1 will install the 1.5.0 version of the package when I run the npm install command.

Is this an issue to use SPFx 1.5 packages ?

Absolutely not, however, there are several considerations to take into account when "upgrading" your projects. But the issue here is mainly that the other dependencies are set to ~1.4.1, the dependencies will then be inconsistent among each others !

Issue when installing dependencies

Dependencies are generally not stored on source control systems. When fetching a SPFx solution from it (to work on it or in a CI pipeline, for instance), the installed dependencies might be different than what you actually expect. Semver describes it pretty well but dependencies will be installed with the latest available versions as:

  • ^1.4.1 => 1.4.1 >= dep < 2.0
  • ~1.4.1 => 1.4.1 >= dep < 1.5.0

Solve the issue

To solve this issue, I made sure that every SPFx dependencies in this project refer to v1.4.1 and on nothing else.

{
    "name": "site-designs-studio",
    "version": "1.1.0",
    "private": true,
    "engines": {
        "node": ">=0.10.0"
    },
    "scripts": {
        "build": "gulp bundle",
        "clean": "gulp clean",
        "test": "gulp test"
    },
    "dependencies": {
        "react": "15.6.2",
        "react-dom": "15.6.2",
        "@types/react": "15.6.6",
        "@types/react-dom": "15.5.6",
        "@microsoft/sp-core-library": "1.4.1",
        "@microsoft/sp-webpart-base": "1.4.1",
        "@microsoft/sp-lodash-subset": "1.4.1",
        "@microsoft/sp-office-ui-fabric-core": "1.4.1",
        "@microsoft/sp-dialog": "1.4.1",
        "@types/webpack-env": ">=1.12.1 <1.14.0",
        "ajv": "~5.2.2",
        "react-sortable-hoc": "^0.6.8"
    },
    "devDependencies": {
        "@microsoft/sp-build-web": "1.4.1",
        "@microsoft/sp-module-interfaces": "1.4.1",
        "@microsoft/sp-webpart-workbench": "1.4.1",
        "gulp": "~3.9.1",
        "@types/chai": ">=3.4.34 <3.6.0",
        "@types/mocha": ">=2.2.33 <2.6.0",
        "ajv": "~5.2.2"
    }
}

Conclusion

Make sure you know the dependencies version you rely on in your project. This will prevent a lot of issues when maintaining your projects. It is actually not only true for SPFx but mainly for all node-based projects. The advice I'd have would be to lock even the revision number in your package.json file, this will force you to know exactly what dependencies your project has, and it will compile properly on any environment. By the way, from SPFx 1.5 generator, the package.json file already lock all dependencies version to 1.5.0 without the tilde (~).

This will help avoid this issue in the future.

[EDIT] As Waldek Mastykarz noticed on Twitter,  using NPM 5 will automatically create a locked version of the package.json file, if for some reasons, you still using NPM 4, you can run the npm shrinkwrap after the creation of your project,

it will have similar effect as locked package.json,

It is actually mentionned in the getting started tutorials, I sadly forgot doing it on my project. Many thanks to him for mentioning this https://twitter.com/waldekm/status/1008961389736726528

As always, I hope this will be helpful for you, please give your feedback and comments!

Cheers,

Yannick

Other posts