lkubuntu

A listing of random software, tips, tweaks, hacks, and tutorials I made for Ubuntu

trivial-require: Closure-friendly Browserify(ish)

… and that title is about as accurate as saying that D is a superset of C, but the most accurate one I could think of that could fit in a relatively small space of text.

Before I explain further, I’ll explain my use-case scenario. I’m writing a web app that is meant to be used on my iPhone. 3G can be used up really quickly by browsing websites, and I plan on using the app a lot, so I need to make sure that the website uses as little bandwidth as possible.

Google’s Closure Compiler is very good at minifying Javascript code (the best I know of), and, under normal circumstances, it works just fine. Thing is, I’m writing the server in node.js, and I want to be able to share the same codebase with both the server and the client. With a tool like Browserify, this becomes very easy.

Problem is, Closure and Browserify don’t match very well. Sure, you can use Closure on a Browserified piece of code, but it doesn’t optimize nearly as well as it could. Few functions are properly inlined or evaluated, many variable and property names stay intact, and there’s a lot of needless code around it.

Use case scenario done. Now on to trivial-require (this line is for the TL;DR people :P)

I wrote trivial-require as a very quick and dirty hack for the project I was working on. It might not be ideal for everyone, but hopefully some people will be able to find it useful as well :)

trivial-require sort of functions like Browserify, in the sense that it will turn node.js code into browser code, and, if the winds are in your favour, it might work.

Okay, that might have been a bit of an exaggeration. This following line will sum up almost exactly what it does (bolded for the TL;DR folk, again)

trivial-require will literally include the contents of the require()d file at the spot where it is require()d. module.exports is entirely disregarded

No extra code is added around it. Literally the only difference between this and C’s #include directive is that this only will include a file once. In other words, var module = require('file'); var module2 = require('file'); will result in file.js being included once (both lines are removed in the output file).

This works in a very different way from the way that browserify and node.js work. But, it is possible to write code that works both with node.js and trivial-require.

Before I go to this though, I’ll explain how to install/run it:

Installing:

sudo npm install -g trivial-require

Running:

trivial-require script.node.js > script.browser.js

Now that that’s done, let’s go to the guidelines on using it:

Do not use ambiguous variable names. It might be overridden by a future module.

// Wrong
var Logger = require('./Logger')("ModuleName");

// Correct
var Logger_ModuleName = require('./Logger')("ModuleName");

Do not use module.exports as a means for writing a function (or other). Any line containing module.exports is deleted.

// Wrong
module.exports = function() {
    console.log("Hello World");
};

// Correct
function HelloWorld() {
    console.log("Hello World");
};

module.exports = HelloWorld;

Use the same module name when require()ing a file. Each file is literally included, and both require() and module.exports lines are deleted.

//// Wrong

// HelloWorld.js
function HelloWorld() = {
    console.log("Hello World");
};

module.exports = HelloWorld;

// index.js
var GreetPlanet = require('./HelloWorld');


//// Correct

// index.js
var HelloWorld = require('./HelloWorld');

require() in the global scope. Caching might hurt you later.

// Wrong
function my_function() {
    var HelloWorld = require('./HelloWorld');
    HelloWorld();
}

// Correct
var HelloWorld = require('./HelloWorld');

function my_function() {
    HelloWorld();
}

require()s containing non-relative pathnames will be removed. Use your own modules instead

// Wrong
var utf8 = require('utf8');

var encoded = utf8.encode("Hello World");

// Correct
var is_node = false;
if (typeof window === "undefined")
    is_node = true;

var encoded;

if (is_node) {
    var utf8 = require('utf8');
    encoded = utf8.encode("Hello World");
} else {
    encoded = unescape(encodeURIComponent("Hello World"));
}

And that’s about it! I hope that trivial-require might be useful for you, and that this guide is clear enough :) If you need help with anything, feel free to leave a comment, and I’ll try to help!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: