Compile an npm module into a single file, without dependencies Compile an npm module into a single file, without dependencies ruby ruby

Compile an npm module into a single file, without dependencies


Browserify has a --standalone flag that can help here.

On the command line:

browserify -s moduleName --bare moduleName.js -o filename.js

In your node script you can import the concatenated module normally:

var moduleName = require('./filename');

However, you will may still need to ignore and/or stub out any tricky modules.


Although it doesn't quite seem like it would be the right tool for the job, it appears that browserify is the closest thing to what you're looking for.

To be complete, here are the versions of the tools I used: Node v0.10.26 and browserify 3.38.0. I didn't test with other version, so they may have problems.

Here are the steps that I took after cloning uncss:

  1. npm install, which downloads and sets up the proper packages
  2. Due to some sort of versioning problem with NPM, I had to manually install the graceful-fs package (a dependency of one of uncss's dependencies) from Github (it wasn't available via npm)

    npm install https://github.com/isaacs/node-graceful-fs/tarball/v2.0.3
  3. At this point, I ran browserify. It turns out that browserify has a --bare flag, which does a couple of things:

    Alias for both --no-builtins, --no-commondir, and sets --insert-global-vars to just "__filename,__dirname". This is handy if you want to run bundles in node.

    With this flag, browserify doesn't inject its own shims for core modules. The full command I used was:

    browserify lib/uncss.js --bare > uncss.js

After doing the above, the file uncss.js contained uncss along with its bundled dependencies. Unfortunately, since browserify wraps everything inside its own require function, the now-bundled modules doesn't export anything initially.

$ node> require('./uncss'){}>

To fix this, I had to change the initial line of the generated bundle from this:

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){

to this:

module.exports = (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require,ex;for(var o=0;o<r.length;o++)ex=s(r[o]);return ex})({1:[function(require,module,exports){

Note: it's not just the module.exports addition - there's some modification in the middle that was needed also*.

After that, the bundle seemed to work:

$ node> require('./uncss')[Function: init]>

*: Essentially, browserify defines an inner function s(o, u) that acts like require. The surrounding code starts off by looping through what looks like a list of "main modules" (in this case, there's just one), requireing them, but not storing the result. It then returns s, the require-like function (why, I'm not sure) as the output of the entire anonymous function. All I had to do was add a variable to store the results, and then return that instead.


While it is not impossible, it is a bit complicated, there is no tool that I know to do it automatically, but it coulb be done manually.

So, if you load a module in this way:

var async = require('async');

You can include the source of that module, first, declaring the module instance in your main script:

var global_async = null;

Then, include the module code inside an anonymous function and replace the "module.exports" with the global var you declared before:

module.exports = async

With

global_async = async;

Problem is that there are a lot of dependencies for "uncss", each one with some dependencies, so it is to much work to be done, but not impossible... but at the end, this module also requires some external binaries like "phantomjs".

If you want to build a gem that create a wrapper around "uncss" you can check if node and uncss are installed before anything, if not, install both, and then just call them, just like uncss does with phantomjs.