How to make 

and

Great Again!

Awesome!

Supreme

...at

Michael K Snead

Why npm/node.js?

  • We write code for the browser, which runs JavaScript
     
  • The de-facto package manager for JavaScript is npm
     
  • Most client-side tooling works with or is developed in node.js (ie: babel, TypeScript, webpack, gulp, grunt, eslint, jscomplexity, Traceur, less, sass, stylus, uglify, browserify, systemjs, jspm, bower, and on ...)
     
  • Microsoft recognizes this, so VS uses a copy of node.js out of the box in VS 2013+ for the built-in Task Runner Explorer window. VS2015 also has support for npm out of the box (including intellisense for package names and versions). Try opening a package.json file!

Challenges

  • Different teams may use and test against different versions of node.js, npm, global dependencies, etc. Agents might not have <xyz> installed.
     
  • "npm install" relies on external 3rd parties, can be slow/unreliable in CI and subject to network failures
     
  • The OOB copy of node.js that Visual Studio uses is super old :(
     
  • If node isn't installed correctly (under the correct user, etc.) things may be broken

Remember when that one guy broke npm?

Let's solve these problems!

Part 1: Include your binaries in source control

node.js itself can be "xcopy deployed"

This means your team can be independent of whatever is installed on the TeamCity agents

Include Binaries in Source Control

  • Install the version of node.js and npm that you want, as well as any global dependencies
  • Copy node.exe, the node_modules folder and npm.cmd from node's installation folder to \Binaries\ in your repository
    You can use "where node.exe" in Windows to find the version you're using.
  • Copy the globally installed modules and their scripts
    These should be under...
    C:\Users\<username>\AppData\Roaming\npm\
    You can also use "where <global>"
    So copy everything inside the npm folder directly inside the binaries folder (not in a subfolder)

Include Binaries in Source Control

Supreme's folder looks like this:

Include Binaries in Source Control

Make sure you add everything, including the node_modules folder in \Binaries\ to source control!

Part 2: Tell Visual Studio to use this copy of node.js

You can either point to the node.js installed on your system (ie: program files) or to the one under \Binaries\.

Your choice.

Part 3: Use the binaries in TC

Supreme uses a simple batch script to kick off gulp/webpack/etc. builds, tests and tasks.

:: We start from \Binaries\ folder when running the script
:: Let's use our \Binaries\ copy of node.js too
SET PATH=%CD%;%PATH%

:: Now let's go tell gulp to build stuff
PUSHD ..\ApplicationTracking\WebApplication\

:: Use CALL or it doesn't work right from batch script
CALL gulp gulp-build

:: Return to \Binaries\
POPD

The key bits are setting the path and using "CALL" to start node-related stuff.

Test this locally before dropping it on TC!

So far we...

  • Use shiny node for Visual Studio
  • No longer tied to whatever is installed in TFS

     
  • Still have problems with npm

Prior to npm3+, which fixes long paths on Windows, Supreme attempted to fix this by 7-zipping the node_modules folder and extracting on build.

 

It was fast. It was reliable in CI.
It was manual and easy to forget to update. :(

Can we ... check in node_modules?

That might work! Some things to consider, though...

  • Could make a mess of merging/PRs (lots of files, needs to be revisited for updates/etc)
  • Even with npm3+, I have >22k files and 8.2k directories under node_modules
  • Breaks cross-platform
    (some modules are native, ie: Windows vs Mac,
    x86 vs. x64, etc.)
  • Still relying on the repository being in sync with all of the dependencies, they're just moved to a different place and no longer compressed
  • Not a best practice for node/npm

To make this less painful I've heard of folks storing node_modules in its own repository...

How about we take it offline?

# Install local-npm
npm install -g local-npm

# Start it up
local-npm

# Point npm at it
npm set registry http://127.0.0.1:5080

# To revert back to npm (why?) run:
npm set registry https://registry.npmjs.org

BOOM!

Much like we use devspare4 for nuget file hosting, we need a machine to run this lightweight node-based server.
(ie: devspare4? devspare 4 1/2?)

Added bonus: if npm ever goes down, Paylocity doesn't have to worry. We no longer spam npm with requests from our CI servers.

How to make

By Michael Snead

How to make

  • 1,665