{"id":2168,"date":"2015-09-30T03:00:00","date_gmt":"2015-09-30T10:00:00","guid":{"rendered":"https:\/\/www.microsoft.com\/reallifecode\/index.php\/2015\/09\/30\/upgrading-to-npm3-on-windows\/"},"modified":"2020-03-18T15:38:32","modified_gmt":"2020-03-18T22:38:32","slug":"upgrading-to-npm3-on-windows","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/ise\/upgrading-to-npm3-on-windows\/","title":{"rendered":"Upgrading to npm@3 on Windows"},"content":{"rendered":"<p>Despite it\u2019s popularity, there were always two major issues with running Node.js on Windows: First and foremost, the operating system maintains a maximum length for path names, which clashes with Node\u2019s traditional way of nesting modules in node_modules. The second issue was a bit more subtle: The npm installer had a set of steps it executed for each package and it would immediately start executing them as soon as it decided to act on a package. This resulted in a bunch of hard-to-debug race conditions and other problems which, from the outside, looked like black, evil magic.<\/p>\n<p>Both issues will soon be history &#8211; we\u2019re now looking at the first build of npm@3, a nearly complete rewrite of Node\u2019s package manager, which will end both of these major issues. This is a huge deal for those of us who built and maintain big Node projects on Windows. This case study describes the development of a small upgrader script, enabling Node developers on Windows to easily upgrade their npm version.<\/p>\n<h2 id=\"the-problem-nested-modules--race-conditions\">The Problem: Nested Modules &amp; Race Conditions<\/h2>\n<p>Previously, your project\u2019s required modules would be installed in node_modules. If they themselves required modules, they\u2019d be installed in\u00a0<code class=\"highlighter-rouge\">node_modules\/{package}\/node_modules<\/code>. The problem is obvious here, but it was surprisingly hard to work around &#8211; solutions involving\u00a0<code class=\"highlighter-rouge\">npm shrinkwrap<\/code>\u00a0and module-flattening techniques existed, but it wasn\u2019t pretty.<\/p>\n<h4 id=\"flat-module-installation\">Flat Module Installation<\/h4>\n<p>Your dependencies will now be installed flat &#8211; by default. If possible, all of your dependencies, and their dependencies, and their dependencies will be installed in your project\u2019s node_modules\u00a0folder without nesting. Nesting will only occur when two or more modules have conflicting dependencies.<\/p>\n<p>Moving forward, deduping is the standard &#8211; and a bunch of commands are dedupe-aware by default. The command\u00a0<code class=\"highlighter-rouge\">npm ls<\/code> will now show you a tree of module requirements and no longer how they are organized on disk. Conveniently,\u00a0<code class=\"highlighter-rouge\">npm uninstall<\/code> removes a package and all it\u2019s requirements &#8211; previously, it just removed those packages that were in its\u00a0node_modules\u00a0folder.<\/p>\n<h4 id=\"multi-stage-installer\">Multi-Stage Installer<\/h4>\n<p>From time to time, we at Microsoft working in the Open Source world had to deal with random race conditions. And when I write \u201cfrom time to time\u201d, I mean \u201call the time\u201d. Npm <a href=\"https:\/\/github.com\/npm\/npm\/issues\/5919\">issue #5919<\/a>\u00a0is now finally fixed, changing the way installation works quite fundamentally. <a href=\"https:\/\/github.com\/iarna\">Rebecca Turner from npm<\/a>\u00a0has been pivotal for the new multi-stage installer (which carefully waits for steps and processes to finish before moving on).<\/p>\n<p>While none of these changes are glaringly obvious to the average user, they will come in handy every single time a developer running Windows executes a big npm build (especially if it involves a bunch of native code). Where npm@2 might run into race conditions and lock-file complications, npm@3\u2019s new installer will succeed.<\/p>\n<h2 id=\"upgrading-npm-on-windows\">Upgrading npm on Windows<\/h2>\n<p>Installing a new version of npm on Windows is a tricky business: By default, npm is installed alongside node in\u00a0<code class=\"highlighter-rouge\">C:Program Files (x86)nodejs<\/code>. Npm\u2019s globally installed packages (including, potentially, npm itself) are stored separately in a user-specific directory (which is currently\u00a0<code class=\"highlighter-rouge\">C:Users&lt;username&gt;AppDataRoamingnpm<\/code>). Because the installer puts\u00a0<code class=\"highlighter-rouge\">C:Program Files (x86)nodejs<\/code>\u00a0before\u00a0<code class=\"highlighter-rouge\">C:Users&lt;username&gt;AppDataRoamingnpm<\/code>\u00a0on the PATH, it will always use version of npm installed with node instead of the version of npm one installs using\u00a0<code class=\"highlighter-rouge\">npm -g install npm@&lt;version&gt;<\/code>.<\/p>\n<p>To save Windows developers from this mess, we wrote a small upgrader tool simplifying the process.<\/p>\n<h2 id=\"implementation\">Implementation<\/h2>\n<p>Since it is fair to assume that developers wishing to upgrade their npm version already have npm and Node installed, we opted for a NodeJS-based solution. The upgrader is installed using npm itself, executed in Node, and uses PowerShell scripts internally to move files, make backups, and upgrade npm.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cse\/wp-content\/uploads\/sites\/55\/2020\/03\/2015-09-30-npm-windows-screenshot.png\" alt=\"Screenshot of the Upgrader\" \/><\/p>\n<p>Let\u2019s look at the actual flow: First, we query npm for the available npm versions and let the user choose one. Then, we ask npm where it usually installs global modules. Once we have those to crucial pieces of information, we kick of a PowerShell script that backs up <code class=\"highlighter-rouge\">.npmrc<\/code> (a npm configuration file) and upgrades npm. In a situation where npm actually does not reside in the global modules folder, we look for it in the NodeJS installation location and upgrade it there.<\/p>\n<p>If you\u2019re interested in some of the source code, you can find it all on GitHub. Some portions readers might be interested in include <a href=\"https:\/\/github.com\/felixrieseberg\/npm-windows-upgrade\">checking the PowerShell execution policy in Node<\/a>, <a href=\"https:\/\/github.com\/felixrieseberg\/npm-windows-upgrade\">checking for Internet via DNS lookup<\/a>, or the <a href=\"https:\/\/github.com\/felixrieseberg\/npm-windows-upgrade\/blob\/master\/powershell\/upgrade-npm.ps1#L34-L80\">surprisingly simple npm upgrade written in PS1<\/a>.<\/p>\n<h2 id=\"running-the-code-installing-npm3\">Running the Code: Installing npm@3<\/h2>\n<p>Before you install npm@3 and use it in production, be warned that this is still beta software, with potentially a bunch of breaking changes and unknown bugs. Obviously, the whole node community and npm are working hard to get it production-ready as quickly as possible. To quote npm: \u201cDuring that time we will still be doing npm@2 releases, with npm@2 tagged as latest and next. We\u2019ll also be publishing new releases of npm@3 as npm@3.0-next and npm@3.0-latest alongside those versions until we\u2019re ready to switch everyone over to npm@3.\u201d<\/p>\n<p>If you\u2019re using Node and npm in the most common ways (to install or publish modules, for instance), npm@3 will most likely improve your life \u2013 if you\u2019re running complex builds, potentially involving a large amount native code, and you have no time to deal with any new issues, you might want to stay clear.<\/p>\n<p>With that disclaimer in mind, here\u2019s how to install and run the upgrader:<\/p>\n<p>First, ensure that you can execute scripts on your system by running the following command from an elevated command prompt (either PowerShell or CMD.exe). To run PowerShell as Administrator, click Start, search for PowerShell, right-click PowerShell and select\u00a0Run as Administrator.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>Set-ExecutionPolicy Unrestricted -Scope CurrentUser\r\n<\/code><\/pre>\n<\/div>\n<p>Then, to install and use this upgrader tool, run:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>npm install -g npm-windows-upgrade\r\nnpm-windows-upgrade\r\n<\/code><\/pre>\n<\/div>\n<p>The tool will show you a list of all the published and available versions of npm (including pre-release and beta versions). Choose 3.1.0 (or newer) and enjoy all the new benefits of npm@3!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Developing large apps with npm and Node on Windows just got a lot better &#8211; npm@3 is here!<\/p>\n","protected":false},"author":21345,"featured_media":12784,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[16],"tags":[275,277,386],"class_list":["post-2168","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","tag-node","tag-npm","tag-windows"],"acf":[],"blog_post_summary":"<p>Developing large apps with npm and Node on Windows just got a lot better &#8211; npm@3 is here!<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2168","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/users\/21345"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/comments?post=2168"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2168\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media\/12784"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media?parent=2168"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/categories?post=2168"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/tags?post=2168"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}