2

Premise: When a new Angular 2+ project is created using the Angular CLI NPM package, a local copy of the CLI is added as a dev dependency to the project: this ensures that when the CLI is used again to add some more elements to the project, the original version - which is installed locally - of the CLI is used even if the globally installed version has been updated in the meantime.


SPFX based projects are most of the time created using the Yeomand based generator provided by Microsoft (@microsoft/generator-sharepoint) or the community maintained PNP one (@pnp/spfx). In both cases, the results of the seeding process is a project with the correct dependencies, folder structure and files for that specific version of the generator.

Microsoft releases new version of the generator quite often. It is not uncommon for a new version of the generator to introduce new features (for example, recently beta support for search extensions was added) - for that reason, newer versions of the generator often also update the version of the depending packages (React, the ui-framework etc).

It is not uncommon as a dev to have to maintain multiple different projects that were created using different versions of the generators. This can result in severe problems: if a generator is run on an existing project - for example to add a new web part - the currently installed version of the generator is used. Obviously, this means that the new generator will uses templates whose dependencies will not match the original ones.

Since it is not always possible to update the old projects to the new dependencies set, I started looking for a way to run an old version of a generator on a project without having to constantly switch the currently installed version.

Sadly, contrarily to what Angular does with the Angular CLI, apparently there is no way to install a Yeoman generator to be used only "locally" in a specific project. Therefore, when Yeoman is used, only globally installed generators are available, with no ability to chose a specific generator version.

Is there a workaround for this? How can one invoke an old version of a Yeoman generator when a new version of the generator has already been (globally) installed?

0

After some further research, it seems that my initial assumptions were wrong.
Technically, Yeoman supports local installation of generators.

In this Twitter thread Simon Boudrias, one of the team members for the Yeoman project says:

We do (support local install), like any other tool you're using on npm.

and

Locally installed generators always take precedence. For yo itself, a locally installed version will be used by npm run (or yarn yo)

Sadly, as Waldek Mastykarz points out in the very same thread, this apparently is not completely true. In my experience a globally installed generator currently will always take precedence on a local one - if you have a global generator installed, installing a different version locally to a project will make no difference. I don't know if this is a bug or the intended behavior, but as far as my understanding goes, the original Twitter thread seem to point to a bug.

Therefore we are left with only two options.

  • Option A: never install a generator globally, only install them locally in a project. So, basically, you first install the needed generator version to your working folder, then run the generator to seed your project. Notice that after the project has been generated, you will have to add the generator again as a devdependency because the generator also overwrites the package.json file.
  • Option B: use NPX to run the generator "remotely". NPX allows you to execute an NPM package without having to install it locally - as an added effect it also allows you to execute remote versions of a package bypassing the locally/globally installed one. By running the command:
    npx -p yo -p @microsoft/generator-sharepoint@x.y.z yo @microsoft/sharepoint
    it is possible to execute the specified generator version as if it was installed locally. The downside is that the generator will have to be downloaded on the fly so one will have to wait a few seconds for the process to complete. Credit to Stefan Bauer for documenting this option here.

Personally, I would prefer Option B, but you are free to choose whatever options is best for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.