slides-modular-javascript



slides-modular-javascript

1 2


slides-modular-javascript

Modular JavaScript With npm and Node Modules

On Github dilvie / slides-modular-javascript

"Absorb what is useful, discard what is not, add what is uniquely your own." ~ Bruce Lee

Modular JavaScript With npm and Node Modules

Eric Elliott

Why Modules?

DRY (Don't Repeat Yourself)

Stay Organized

Maintain Separation of Concerns

Domain logic

Presentation

Different Modules

Why Node Style Modules?

Stupid Simple Syntax

Export Something

'use strict'; // You should always do this.

var foo = function () {
  return true;
};

module.exports = foo;

Import Something

var foo = require('./foo.js');

foo(); // true

Unbeatable ecosystem

Great Package Management

Keep all modules in Git

Principles of Modularity

Modules should be:

Specialized

DOT (Do One Thing)

Independent

  • Do something useful independent of the app.
  • Don't grab stuff from globals.
  • Avoid implicit stateful dependencies.

Decomposable

  • You should be able to test your modules outside your app.
  • Like component entertainment center.

Recomposable

  • Should be possible to rearrange the modules to build a different app.

Substitutable

  • You should be able to swap out one module for another, as long as they share the same public interface.

Open / Closed

Open to extension, closed to modification

Interfaces

"Program to an interface, not an implementation."

~ GoF, "Design Patterns"

Interface is a Contract

  • Enables substitution

Obey the Open / Closed Principle

Export Your Public API

Encapsulate Your Implementation

  • Easy - just don't export it!
// Not exported.
var fullName = function fullName(firstName, lastName) {
  return firstName + ' ' + lastName;
}

module.exports = function person(options) {
  return {
    firstName: options.firstName,
    lastName: options.lastName,

    // Hides internal implementation.
    name: function name() {
      return fullName(this.firstName, this.lastName);
    }
  };
};

KISS (Keep It Simple, Stupid)

Keep It Stupid Simple

It’s not the daily increase but daily decrease.

Hack away at the unessential. ~ Bruce Lee

Export One Function

  • Principle of high cohesion

Lame:

module.exports.foo = function () { return 'foo'; };
module.exports.bar = function () { return 'bar' };
module.exports.baz = function () { return 'baz'; };
var foo = require('lame').foo,
  bar = require('lame').bar,
  baz = require('lame').baz;

Better - different modules.

var foo = require('foo'),
  bar = require('bar'),
  baz = require('baz');

High cohesion warrants object factories:

var http = require('http'),
  server = http.createServer();

server.listen(3000, function () {
  setTimeout(function () {

    server.close();

  }, 30000)
});

Don't Export Constructors

Breaks open / closed principle

var Widget = require('widget'),
  myWidget = new Widget('clock');

Can't turn widget into factory

  • All callers are expecting to use new

Do Export Factories

var widget = require('widget'),
  myWidget = widget();

Inside the widget factory:

module.exports = function widget(options) {
  return {
    name: options.name,
    el: document.createElement(options.tagName || 'div'),
    template: '<div class="content"></div>'
  }
};

Factory flexibility

Stampit: Compose factory functions.

module.exports = function (options) {
  return stampit.compose(widget, eventEmitter,
    list, touch, intfiniteScroll);
};

Modules instead of inheritance

Better way to reuse stateless functions

Objects are only needed for state

  • Configuration
  • User data
  • Domain objects

npm - not an acronym

Node Packaged Modules (60k+175/day)

Bundled with Node

http://nodejs.org/download/

Version using semver

major.minor.patch

  • major = breaking changes
  • minor = new non-breaking features
  • patch = bug fixes, insignificant changes

package.json

  • name
  • version
  • author
  • description
  • keywords
  • repository
  • license

more package.json

  • main
  • scripts
  • dependencies, bundledDependencies
  • devDependencies
  • private

Public and private dependencies:

"dependencies": {
  "public": "git://github.com/user/repo.git#ref",
  "private": "git+ssh://git@github.com:user/repo.git#ref"
}
$ npm init
$ npm version <major|minor|patch>
# Publish publicly!
# Get famous!
# Make friends!

$ npm publish

Run scripts

npm run <script-name>

Good idea

$ npm run jshint

Browserify

require(‘modules’) in the browser.

Install

$ npm install -g browserify

Compatible with most Node modules

(~60k modules)

Node core modules in the browser:

  • events
  • stream
  • path
  • url
  • assert
  • buffer
  • util
  • querystring
  • http
  • vm
  • crypto

Create your bundle

$ browserify index.js -o bundle.js

With source maps

$ browserify index.js -o bundle.js --debug

Create your minified bundle

$ browserify index.js | uglifyjs -c > bundle.min.js

Or use a transform...

$ browserify -t uglifyify index.js -o bundle.min.js

Other transforms

  • Coffeescript
  • CSS requires
  • AMD
  • Bower
  • Component
  • ES6

https://github.com/substack/node-browserify/wiki/list-of-transforms

Compile UMDs

$ browserify -s <namespace> index.js -o bundle.js

Module will be at window.namespace

Already using AMD? SWitch!

https://github.com/thlorenz/browserify-ftw