The npm workflow

EnterJS, 2016-06-16

Who is this guy?

Laurie Voss

CTO, 

@seldo

Calibration

What are we talking about?

  1. Basics of npm
  2. Building a project
  3. Sharing a project
  4. Managing dependencies
  5. Managing project lifecycle
  6. Automation with npm

Why use npm?

npm      modularity

Front end development is embracing modularity

Apps can be packages

The npm workflow

Hold. Up.

npm basics

Part 1

npm architecture

Where downloads come from

What about GitHub?

npm does not* download packages from GitHub

* not usually, and not by default

The registry can host private packages

npm Enterprise

Building a project

Part 2

npm install -g npm
npm install -g npm@lts

or

npm init

npm init --yes

Scopes

npm init --scope=myusername

npm install @myusername/mypackage

var x = require('@myusername/mypackage')

~/.npm-init.js

and PromZard

npm init can be re-run

Avoiding editing package.json

> npm install --save 
> npm install -S 
> npm install --save-dev 
> npm install -D

Skip devDependencies in production

> npm install --production

bundledDependencies

Offline* Installs

* mostly

npm install --cache-min 999999
npm config set cache-min 60

Install only from local cache

Check metadata less aggressively

Run scripts

npm start
npm stop
npm restart
npm test
{
  "name": "@seldo/some-package",
  "version": "1.0.0",
  ...
  "scripts": {
    "test": "mocha ./test/*.js",
    "start": "node ./index.js"
  }
}

Run scripts get devDependencies

in path

Publishing

npm publish
npm publish --access=public
npm publish --access=restricted

Part 3: sharing a project

SemVer

Semantic Versioning

2.15.58

Breaking

major

Feature

minor

Fix

patch

SemVer reduces friction

Versioning

npm version major
npm version minor
npm version patch
npm version major -m "bump to version %s"

SemVer is a promise

not a guarantee

Shrinkwrap

(...but...)

npm install clingwrap -g

Maybe try

Multiple users

npm Organizations

npm team
npm access

npm team

npm team create  <scope:team>
npm team destroy <scope:team>
npm team add     <scope:team> <user>
npm team rm      <scope:team> <user>
npm team ls      <scope:team>

npm access

npm access grant read-only  <scope:team> [package]
npm access grant read-write <scope:team> [package]

npm access revoke           <scope:team> [package]

npm access ls-packages [user|scope|scope:team]

npm access ls-collaborators [package [user]]

Multiple packages

npm link

Part 4: managing dependencies

npm link: how-to

npm link

In your package "@myuser/bob":

In your other package, which requires "@myuser/bob":

npm link @myuser/bob

Multiple current versions

npm publish --tag
npm dist-tag 

npm publish --tag

npm publish --tag <tag>
npm install <pkg>@<tag>

Try it out:

npm install npm@next

to try out next week's release

npm dist-tag

npm dist-tag add <pkg>@<version> <tag>
npm dist-tag rm <tag>
npm dist-tag ls <package>

npm install --tag

npm unpublish

(you may have heard about this one recently)

npm unpublish <pkg>@<version>

npm deprecate

npm deprecate <pkg>[@<version>] <message>
npm deprecate bob@1.0.1 "Breaks everything"

e.g.

Keep projects up to date

npm outdated
npm update
Package     Current  Wanted  Latest  Location
domutils      1.3.0   1.3.0   1.5.1  @npm/testnpm
handlebars    1.3.0   1.3.0   4.0.5  @npm/testnpm
hbsfy         1.3.2   1.3.2   2.7.0  @npm/testnpm

Run scripts, again

npm run $anything
    "npmcheckversion": "node ./internals/scripts/npmcheckversion.js",
    "preinstall": "npm run npmcheckversion",
    "prebuild": "npm run test && npm run build:clean",
    "build:clean": "rimraf ./build/*",
    "build": "cross-env NODE_ENV=production webpack --config internals/webpack/webpack.prod.babel.js --color -p",
    "analyze": "node ./internals/scripts/analyze.js",
    "start": "cross-env NODE_ENV=development node server",
    "start:tunnel": "cross-env NODE_ENV=development ENABLE_TUNNEL=true node server",
    "start:production": "npm run build && npm run start:prod",
    "start:prod": "cross-env NODE_ENV=production node server",
    "pagespeed": "node ./internals/scripts/pagespeed.js",
    "presetup": "npm i chalk",
    "setup": "node ./internals/scripts/setup.js",
    "clean": "shjs ./internals/scripts/clean.js",
    "generate": "plop --plopfile internals/generators/index.js",
    "lint": "npm run lint:js && npm run lint:css",
    "lint:js": "eslint . --ignore-path .gitignore --ignore-pattern internals/scripts",
    "lint:css": "stylelint ./app/**/*.css",
    "lint:staged": "lint-staged",
    "pretest": "npm run lint",

Don't read this. Just remember "there were lots of examples".

Part 5: managing project lifecycle

Run script environment

npm_package_name
npm_package_version
npm_package_dependencies_request
npm_package_dependencies_express
npm_config_node_version
npm_config_registry
console.log(process.env.npm_package_name)

e.g.

Package configuration variables

{
  "name": "@seldo/mypackage",
  "config": {
    "port": "80"
  }
}
console.log(npm_package_config_port)
> 80

> npm config set @seldo/mypackage:port 8080

console.log(npm_package_config_port)
> 8080

Lifecycle hooks

publish:   prepublish, publish, postpublish
install:   preinstall, install, postinstall
uninstall: preuninstall, uninstall, postuninstall
version:   preversion, version, postversion
test:      pretest, test, posttest
stop:      prestop, stop, poststop
start:     prestart, start, poststart
restart:   prerestart, restart, postrestart

.npmrc

per-project:   /path/to/my/project/.npmrc
per-user:       ~/.npmrc
global:           $PREFIX/etc/npmrc
built-in:          /path/to/npm/npmrc

.npmrc auth

//registry.npmjs.org/:_authToken=00000000-0000-0000-0000-000000000000

Looks like:

//registry.npmjs.org/:_authToken={$NPM_TOKEN}

For CI, try:

More details:

Automation with npm

Part 6

The wombat CLI

npm install wombat -g

Webhooks

Fired after every:

  • publish
  • tag
  • star

wombat hook add

wombat hook add @myco/package https://my.co/myhook some-secret

3 types of webhook

wombat hook add somepackage
wombat hook add @myco/package


wombat hook add @myco


wombat hook add --type=owner @anyuser

Packages:

Scopes:

Users:

More wombat hook

wombat hook ls

wombat hook update <hook-id> https://new.co new-secret

wombat hook rm <hook-id>

Listening for webhooks

npm-hook-receiver

var makeReceiver = require('npm-hook-receiver');
var server = makeReceiver({
	secret: 'my-secret',
	mount: '/hook'
});
 
server.on('package:publish', function(package)
{
	console.log(`${package.name} was updated!`);
});

Why webhooks?

Lets you build the features we're missing.

Some early hook apps

The non-npm workflow

Babel

Transpile all the things!

Webpack

and

Browserify

Greenkeeper

greenkeeper.io

"npm outdated" as a service!

Node Security Project

npm install nsp -g
nsp check

Recap!

architecture

npm update

npm init

auto saving

.npm-init.js

devDependencies

bundledDependencies

offline installs

run scripts

publishing

SemVer

npm version

shrinkwrap

npm team

npm access

npm link

dist-tags

unpublish

deprecate

outdated

lifecycle events

.npmrc files

webhooks

...and more!

The bigger picture

npm wants to make your life easier

The web is

coming to npm

Really, it's been here for some time.

npm: the registry for

  • node
  • jQuery
  • Grunt
  • Gulp
  • Ionic
  • Cordova
  • Nodebots
  • Babel
  • Atom
  • TypeScript 2
  • Angular
  • Ember
  • React​
  • Several thousand web frameworks
  • More!

npm       you

What can npm do for you?

Publish your apps to npm

Hook into your automation.

 

The more we know, the more we can help.

Coming soon: add-ons

Making the registry do more for you:

  • security scanning
  • license auditing
  • code quality metrics

npm is just

getting started

One last thing

For lesbian, gay, bisexual, transgender, and queer people of all kinds in tech.

(this is nothing to do with npm)

Thank you!

npm      you

Follow me on Twitter for no reason!

@seldo

Good questions get t-shirts!