
Browserify handbook - mambodog
https://github.com/substack/browserify-handbook
======
mikegioia
I must say, there was a bit of a learning curve to Browserify. Now that I have
it working I feel it's one of the best tools we have for front-end
development.

I auditioned Component and RequireJS but both of those felt like a kludge.
Browserify lets you do node style includes as well as compile your JS into
separate bundles.

I wrote a very small structure and build system [1] for our front-end projects
at work that uses Browserify / Gulp and can compile everything into separate
modules. It uses nginx/apache for routing and since it's all HTML/CSS and
compiled JS, it's lightning fast to deliver.

I think this guide is fantastic; we just need more things like this to lower
the barrier to entry.

[1]
[https://github.com/TeachBoost/mishra](https://github.com/TeachBoost/mishra)

------
untog
I'm so very glad that Browserify exists. After living in RequireJS/Bower/etc.
hell it really is a breath of fresh air.

~~~
voidfiles
What problems did you run into while using RequireJS?

~~~
untog
I write with Node in the backend and JS on the front-end, so switching between
CommonJS and RequireJS styles was a source of constant irritation (and let's
face it, the RequireJS style is annoying). I tried using the CommonJS style in
RequireJS but I could never get it to behave correctly.

Also, though I found bower useful I disliked having yet another package
manager, yet another manifest and yet another install step included in my
development workflow. Using npm for both server and client side modules has
been a dream.

~~~
Touche
With Browserify you have extra steps as well. Install browserify. Install a
watch thingy (in grunt or gulp or write a shell script or whatever). Remember
to run that watch thingy every time you develop.

That's why I prefer client-side loaders. All you have to do is copy the loader
into a folder and create a .html file. I have my dev folder hosted by apache
so I don't ever have to worry about starting some process, running npm install
and watching it install the entire internet, etc.

~~~
cnp
When people complain about these types of "steps", it makes me wonder if
they're not thinking clearly about what these steps actually mean, especially
for larger projects or when working on a team where synchronization is
absolutely key. These processes are here to _help_ you _help yourself_.

Steps like these allow you to systematically control every aspect of the
development process, and adapt. In the long run, these steps work in your
favor.

They also allow you to hook into the more modern aspects of development. I
mean, you don't want to type `npm install` --that's fine; what you're
essentially saying is that this incredibly useful ecosystem is irrelevant to
your needs. I find that very hard to believe.

~~~
Touche
You misunderstand me. The benefit of a client-side loader is that these things
can be added gradually. That doesn't mean you don't use many of the same
tools. There's just not that 15 minutes of setting up your project folder, and
of course not having to run a watch task every time you develop.

------
hamburglar
Browserify is awesome, and I look forward to reading this guide in detail, but
I must say I'm disappointed about the "avoiding ../../../.." section. I've
never seen a solution to this problem that wasn't a hack. The doc is correct
that using NODE_PATH makes your app "tightly coupled to a runtime environment
configuration", but what it fails to note is that the other two solutions
offered are just as ugly. Checking code into a directory managed by npm is
simply asinine, and putting symlinks in there is just as "coupled to the
runtime environment configuration" as the NODE_PATH solution. What is really
needed is a reasonable (and _supported_ ) method of programmatically managing
the node search path.

Why the node community is so stubborn about this point is a mystery to me and
it makes me wary of node in general, because who wants to be locked into an
environment where such an obvious pain point is ignored due to stubbornness?

~~~
cshenoy
Do you have a better solution in mind? I'm actually wondering because I've
thought of workarounds but they'd all be hacks like the ones in the handbook.
I'd imagine other node developers are in the same boat (not due to
stubbornness) otherwise we would've seen something by now.

Basically, what would be your ideal solution?

~~~
indirectlylit
There are good discussions of this issue at
[https://gist.github.com/branneman/8048520/](https://gist.github.com/branneman/8048520/)
and
[http://stackoverflow.com/questions/10860244/](http://stackoverflow.com/questions/10860244/)

My preference is to add structure with file names instead of directories:
app.foo.bar.js instead of app/foo/bar.js

~~~
hamburglar
Unfortunately in that first link, isaacs is on record as saying we should just
check our code into a node_modules directory. "Problem solved." This is
exactly the kind of stubbornness I'm talking about.

~~~
garthk
All the pain and exhaustion is a sign you're fighting your way uphill instead
of downhill. Node works brilliantly if you publish lots of tiny modules in
public, @substack style.

Unfortunately, some of us need to live uphill.

I find the tiny module style works pretty well for me, but I need private
code. I haven't yet found a private registry solution I like. NPM's lack of
support for any "get this module from this registry" directive in package.json
forces them to proxy the main registry. They're not good at it. I'm still
declaring my dependencies by tarball URL, losing semantic version specs, e.g.
"most recent compatible with 4.x".

It strikes me as unlikely now to change in any way other than "here, use my
paid-for private registry", because shareholders. That makes me unhappy, but
not unhappy enough to ditch the public Node ecosystem and go back to what I
was using before. It had its own uphill, and living there was harder.

~~~
hamburglar
One thing that amazes me is the arrogance with which people who like this
scheme can make pronouncements about right and wrong ways to organize code.

From the most popular answer on the stackoverflow link: "If you find yourself
loading common files from the root of your project (perhaps because they are
common utility functions), then that is a big clue that it's time to make a
package."

I'm sorry, but no, that is _not_ a big clue that it's time to make a package.
Every project I've ever worked on contained internal modules which were nicely
organized and isolated, and were consumed by the rest of the project as black
box "libraries" for good design's sake, but breaking them out into separately
installable modules would have been sheer, unproductive bureaucracy. Oops, you
made your code modular! Get ready to start managing packages!

It's as if npm no longer wants to be merely a package manager, but also have a
say in how your project internals are laid out as well. Perhaps it's a self-
perpetuation strategy.

~~~
garthk
I think you might be attributing stronger emotional intent than is present.
They disagree about whether it's worth fundamentally changing npm's search
method to avoid some ../.. paths in your argument to require. require aside,
you can express yourself through your code however you like.

------
Kiro
I keep wondering what kind of applications people build where they have so
many dependencies that they need something like Browserify. Am I the only one
doing the 1. find CDN link 2. add script tag to body?

~~~
cnp
If you've ever worked in other languages that have an "import" function,
you'll understand. Having to manually manage script tags, order of operations,
rapidly growing 2000 loc script.js files, etc, can only lead you astray,
introduce errors, and make debugging your code hell.

// App Controller

var AppModel = require('./models/AppModel');

var NavView = require('./views/NavView');

var HomeView = require('./views/HomeView');

// Do stuff

You can immediately know whats going on inside of your class or module simply
by looking at the imports, the LOC is greatly reduced, and refactoring, via
imports, makes your code about a thousand times more maintainable.

~~~
sync
You mean like the "import" function in ES6?

~~~
cnp
Yup ;)

------
dugmartin
I've been working on a front-end project in CoffeeScript using React and
running Browserify via Gulp has been both a great time saver and has helped
keep my project organized.

One tip I can give is that I ended up organizing each of my React components
and mixins as a module in their own folders and files and my gulpfile adds the
parent source path to the NODE_PATH environment variable. By adding the
coffeeify transform and .coffee extension to the browserify gulp task I can
just do this in my code:

    
    
        SomeComponent = require 'react-components/some-component'
        SomeMixin = require 'react-mixins/some-mixin'
    

No need to worry about relative paths or if it is CoffeeScript code or plain
Javascript.

The other tip is to NOT require react within your browserfied code. Just load
it as a script tag before your browserfied code and use window.React to get a
reference.

~~~
sanderjd
Huh, care to expand on why you shouldn't `require` React? Just doesn't play
nicely with Browserify?

~~~
dugmartin
Yeah, sorry I wasn't clear why. The first is that React is pretty large so it
slows down the watch/build cycle enough that there is a lag and second is that
in production React can be loaded via a cdn. Since everything is bundled into
one file with Browserify its better for the end user download speed if you
pull 3rd party libs out.

I also didn't give the main reason for using the NODE_PATH method. Browserify
doesn't resolve duplicate relative paths so if you have a structure like this:

    
    
        /src
          main.js
          components/a.js
          components/foo/b.js
          components/foo/c.js
    

and a.js requires c.js via relative paths:

    
    
        require('./foo/c.js')
    

and b.js also requires c.js via

    
    
        require('./c.js')
    

then c.js is included twice in your bundled code since Browserify uses the
pure string path as the key. If instead you put /src in your NODE_PATH you can
do this in a.js:

    
    
        require('components/foo/c.js')
    

and this in b.js

    
    
        require('components/foo/c.js')
    

and c.js will only be bundled once since it has the same path.

~~~
sciolistse
I'm not sure that's accurate.. I've been using Browserify for some time, and
write code like that pretty much all over (require('../lib/api'),
require('./api'), etc.) without having file duplication issues in the bundled
output. Do you have an example that exhibits the problem?

Also, if you're requiring large files that you know won't need processing by
browserify (like react), you can use the 'noparse' option to prevent the
performance hit during bundling. (Of course a cdn is potentially a better
option.)

------
ghostwords
Here is a browserify/watchify-based script I use for building a browser
extension's JS bundles:
[https://github.com/ghostwords/chameleon/blob/master/tools/bu...](https://github.com/ghostwords/chameleon/blob/master/tools/build.js)

The script

\- Creates multiple bundles, with Underscore template precompilation and
source code minification (for some bundles).

\- Converts every vendor library into shared modules (you don't want
Underscore included in every bundle that needs it, but you want to be able to
require() it in those bundles).

\- Monitors your files for changes and recompiles bundles as needed when run
with --watch.

I found working with Browserify a pleasant experience after RequireJS and r.js
(its build tool).

------
flog
A printable version: [https://gitprint.com/substack/browserify-
handbook](https://gitprint.com/substack/browserify-handbook)

~~~
rming
Wow, what a great app. So simple and easy to use. Love it!

------
BenjaminCoe
I played with Browserify for the first time two weeks ago, building this app:

[https://github.com/bcoe/npm-typeahead](https://github.com/bcoe/npm-typeahead)

Both the libraries that the app depended on (typeahead.js, and jquery) had
been published to npm. I found it really straight-forward to setup an asset-
pipeline using Browserify.

I'm a big fan :)

------
bkurtz13
I came across and played with beefy[1] today. Has anyone here integrated it
into their workflow?

[1] [http://didact.us/beefy/](http://didact.us/beefy/)

~~~
mattdesl
I use beefy for almost all my modules, demos, and protoypes. For websites, I
usually go with gulp watch since I need LESS anyways.

------
eranation
Anyone has luck with Browserify + TypeScript while keeping source maps
pointing correctly back to TypeScript? (or any other JS transpiler)

~~~
chamakits
I recently also started using Browserify with Typescript (along with tds to
get some ambient files for popular libraries). I got it to work after tryping
countless of hacky things.

What I ended up with was a seperate ts file that is just the module, and
variables I export. See this:

[http://jsbin.com/gidaneja/1/edit?js,output](http://jsbin.com/gidaneja/1/edit?js,output)

So I do a "<reference path=" for the ambient paths of variables. Then I
declare require so I can call browserify's require. Then I create a function
with it's return type being used based on ambient files I included. Then I
create an export variable and call the function to set it's value. Then I can
use that variable without a problem everywhere.

I tried using the whole "import lodash = require('lodash.d.ts') thing and
other variations and failed miserably. This is the only thing I got to work,
and its working perfectly. Email me (email should be on my profile) if it's
not clear, I know the explanation was kinda vague.

~~~
eranation
Awesome, thanks! will try it :)

~~~
chamakits
Happy to help. Let me know how it goes.

------
oulipo
I use browserify and I'm happy with it, but I have one question that perhaps
someone can answer :

how can I develop a library with different modules, say lib/module/func,
lib/module/other, and compile the library as static, then import it in another
project and be able to require lib/module/other from the other project using
only the compiled lib?

~~~
mattdesl
Why compile the module? Browserify lets you use a module's CommonJS export, so
the only build step is at the application level. Utils etc should not be built
except for non-node users (umd).

~~~
oulipo
It would allow to distribute and package the library simply, rather than
having to checkout the library in the other projects dir and have weird
require(../../lib/module/other)

~~~
mattdesl
We must be doing different things. If I start getting relative paths like
that, I usually pull it out into a separate module.

I can understand bundling a bunch of modules together for UMD builds, but if
you need to bundle all of your NPM/browserifiable modules _for_ other
browserify apps, you are probably going about it the wrong way..

------
DEADB17
After using browserify for a while now, I recently came across webpack
([http://webpack.github.io/docs/what-is-
webpack.html](http://webpack.github.io/docs/what-is-webpack.html)) which I'm
finding more convenient and as efficient.

Advantages:

\- requiring and pre-prosessing files other than js is easier

\- ability to use AMD modules if you have to

\- code splitting

------
jaekwon
Here's a simpler alternative if you don't want all the bells and whistles of
Browserify

[https://github.com/jaekwon/demodule](https://github.com/jaekwon/demodule)

------
mateuszf
Anyone knows how to use bootstrap using commonjs/browserify? I don't want to
use neither bower nor manual download / storing compiled bootstrap inside of
project.

~~~
Kenan
[https://github.com/ForbesLindesay/twbs](https://github.com/ForbesLindesay/twbs)

~~~
mateuszf
Thank you very much!

------
kelkes
Main problem is when npm modules are not up to date. This is the reason i
still have to use bower but debowerify helps a lot...

~~~
cwmma
require('name/repo#commitish') works with npm/browserify, considering that
bower uses git repos you can require them that way.

