Three usage scenarios with browserify

browserify

Some prior words on browserify debug mode

First of all, remember that browserify will, by default function in debug mode.

That is why the first time you try browserify you’ll see a lot of gibberish characters appended to the browserified file.

Every scenario described here, has its own way of disabling the debugging (i.e. disabling source maps).

Browserify as a command line tool

This is the regular usage promoted by everyone. You write a CommonJS file and then ask Browserify (installed as a command line tool) to bundle it.

npm install -g browserify
touch index.js
echo "console.log('Hello world')" > index.js
browserify index.js > bundle.js

I won’t get into much detail here because this is the most common usage for browserify.

The next scenarios I describe here are not optimal because these are heavy in terms of parsing and compiling but there are handy in several situations.

Browserify as an express middleware

Maybe you want to have your browser code source files somewhere and make them available to the browser on an express route browserifying them on the fly, instead of having to process them via the commmand line.

You can use the browserify-middleware module for helping you achieve that.

This examples I put down here are the ones in the README.md for browserify-middleware but I explain two of the examples in little more detail.

Serving a single file browserified on-the-fly at a specific path

var browserify = require('browserify-middleware');
var express = require('express');
var app = express();
//provide a browserified file at a path
app.get('/js/file.js', browserify('./client/file.js'));
app.listen(3000);

The ./client/file.js file path are relative to __dirname of caller, not relative to process.cwd().

Serving multiple files browserified on-the-fly under a common base path

Let’s say you want to offer several browserified files under /js/*

var browserify = require('browserify-middleware');
var express = require('express');
var app = express();
//provide browserified versions of all the files in a directory
app.use('/js', browserify('./client/dir'));
app.listen(3000);

Browserify will try to load whatever /js/foo.js file you ask via HTTP, find it in the client/dir directory and browserify it according to its own require() statements. Then, the browserified version will be served by express individually at each path.

The ./client/dir path is relative to __dirname of caller, not relative to process.cwd().

You can check the full API for browserify-middleware in order to improve your usage.

As a module. A.k.a. API usage.

This scenario allows you to create a Buffer, an stream or a String containing the browserified code instead of serving it via HTTP or relying on a UNIX command line for piping the output of browserify as a command line tool.

Getting a stream for piping it

var browserify = require('browserify');
var b = browserify();
b.add('./browser/main.js');
b.bundle().pipe(process.stdout);

Getting a buffer from the browserify API

If you pass a function to browserify’s bundle() method, it won’t return an stream. Instead, it will call that function with an error-first argument and the browserified code as second argument if nothing bad happened when browserifying.

var browserify = require('browserify');
var b = browserify();
b.add('./browser/main.js');
b.bundle(function(err, code) {
  // Here `code` is a Buffer.
});

Getting a string from the browserify API

This is the same as getting a buffer, but calling the .toString() method on the Buffer.

var browserify = require('browserify');
var b = browserify();
b.add('./browser/main.js');
b.bundle(function(err, code) {
  console.log(code.toString());
});

The full API for this kind of usage is documented here.

Sharing Express session data with socket.io

How to access the cookie-based session data of an express app from a socket instance

What do I mean with Sharing Express session data with socket.io?

Well, if I have an express app and a socket.io server instance, both attached to the same http or https server, what I would like, is to be able to get, in socket event handlers, the cookie-based session data from the express app (session data created using a module like express-session).

That is, I would like to be able to do something like…

socket.on("logout", function() {
  // ...
  session.user = null;
  // ...
});

… and trust that every Express middleware will be aware of that session data modifcation. I.e. I want req.session altered when the socket handler alters the session data.

socket.io middleware

Starting from socket.io 1.x, we have the concept of middleware too. So, as the docs for io.use() state:

a middleware is a function that gets executed for every incoming Socket and receives as parameter the socket and a function to optionally defer execution to the next registered middleware.

What we can do in order to share session information is to fetch the session data we created for express and make it available on every socket by reusing middleware.

Reusing express middleware in socket.io

The handshake property on every socket

Every socket on the server side, has a handshake property with information about the first steps in the creation of the socket. The handshake property is set up on socket creation, so when you do io.on(“connection”, function(socket){}) , you already have socket.handhsake created in the new socket.

That’s the ideal place to store session data if we want to get it on every event handler we attach to a socket.

Combining express middleware and socket.io middleware

An Express middleware function has this signature:

function(req, res, next) {}

and a socket.io 1.x middleware function has this signature:

function(socket, next) {}

… So, all we have to do is to to create an io.use() compatible function that calls the express session middleware…

var session = require("express-session")({/* ... */});
app.use(session);
var iomiddleware = function(socket, next) {
  var req = socket.handshake,
    res = {};
  // let the session function act like:
  // - store req.session in socket.handshake, 
  // - use an empty res object
  // - call socket.io's next() midleware
  //   when the session middleware is done.
  session(req, res, function() {
    next(); 
  });
}
io.use(iomiddleware)
io.on("connection", function(socket) {
});

Show me a module for doing that in a simpler way.

In order for making things simpler, I wrote this module: express-socket.io-session.

You use it by:

// Regular instantiation of express-session
var session require("express-session")({
    secret: "my-secret",
    resave: true,
    saveUninitialized: true
});
// Regular use of express-sessions with express
app.use(session);
//Share the express session with socket.io
io.use(require("express-socket.io-session")(session));

There are a couple of libraries that set up session for socket.io 1.x but they differ from express-socket.io-session in the way they are instantiated.