Browserify VS Webpack - JS Drama

A simple Gist by Substack, the author of Browserify has caused much drama in the javascript community. A lot has been said about modularity vs the kitchen-sink approach.

While on the one hand, Substack talks about how bundling features into a single project hurts Semver and hurts competition, Pete Hunt is sick of this ‘modularity shaming’ and points out that the Webpack codebase is extremely modular.

I see some good points on either side of the story, but I think the major difference between the two projects is something else entirely:

Compatibility with node.js

 Browserify

Browserify was born to make your Node code in the browser. Till date it only supports the node flavour of commons (including JSON support) and provides in-built shims for many node core modules. Everything else is a different package. Need to watch files for incremental compilation? Use Watchify. Need Bundle splitting? Use Factor-Bundle. Need AMD support? Use deAMDify.

Browserify pushes all features that don’t fit into it’s philosophy of running Node code in the browser into transforms and plug-ins.

At the same time, Browserify expects to be used only in a Node.js project. It recommends making small modules and posting them on NPM, and putting any configuration into the package.json file.

 Webpack

Webpack is a very different beast. It learnt from tools such as Browserify, and Require.js and it never tries to actually be compatible with node.js. It is built, from the ground up, to help you manage static assets for the front-end. So, while in Browserify, to read strings from static files, you would use BRFS, which uses the native readFile function in Node, in Webpack, the common thing is to just overload the require function and use a loader that loads files that have names that match a certain pattern.

Webpack also doesn’t have any preference for commonjs over AMD. It supports all modules formats out of the box. So you could write your entire project with AMD, and still use Webpack. Obviously, that code isn’t going to work in Node without some work.

 Differences in Philosophy

These differences can have far reaching consequences. Webpack for example applies loaders to all files that match, unless you manually exclude the node_modules folder. Browserify, by default, will not apply any transform to files in the node_modules folder by default.

This is actually an interesting detail when comparing the two systems. Browserify is a smaller more 'modular’ tool that can and should be composed with many plug-ins and transforms. Webpack, brings more features and puts them in core. But Browserify is more convention driven than webpack.

Webpack, for all its size and features is actually pretty flexible in its usage. You can use it in various ways as long as you’re willing to write a long enough config file.

If you only use commonjs and don’t use webpack for managing any CSS or images, then you could, use it like browserify and maintain compatibility with node. But webpack doesn’t try to conform.

Browserify on the other hand, being smaller and more established is easy to pick up. And if you conform to some of its conventions, you have write very little or no configuration to make it work.

So, Browserify is much more likely to work with minimal configuration but will force you into a small set of conventions. Webpack on the other hand will always require some configuration to work for anything but the most basic case.

 Static asset management

Webpack with require overloads will let you require CSS files that can be injected in the browser at runtime. Node.js can’t exactly require CSS files though. But with Webpack, you have to configure it the way you like.

In the Browserify world, you would solve the same problem with conventions and modularity. With the tool, Parcelify, which is complementary to Browserify, you can track your dependency graph, and using package.son files in modules, require CSS files that happen to be packed with your javascript packages. This system will try to force you into composing your apps into many modules with their package.json files, which may, in the long run help you make your entire codebase more modular and reusable.

Similarly for images and other static assets where all you want is the URL to a file and nothing else, browserify has a tool called urify-emitter. It’s currently in an experimental stage, but it brings Webpack like static asset management in a way that is completely compatible with Node. Instead of overloading the require function, it introduces a package, that you can 'require’ static assets with. The required files, just return a simple string which is the path to that static asset. With some configuration, you can make it automatically copy your assets to a particular folder with unique hashed names. When ready, I believe this would be an improvement over asset management in JS that webpack make popular.

 Bundle Splitting

A lot has been said about Webpack’s built-in bundle splitting. However, with Factor-Bundle and Partition-Bundle, Browserify has the same capabilities.

 React Hot-Loading

One area where webpack is way ahead of Browserify is the webpack server utility that can be used for cool features such as React Hot-Loading that updates javascript on your pages without a page refresh. It can be pretty difficult to set-up, but is an amazing tool once you have it.

 Webpack’s fix for Node.js

If you do go down the Webpack route, it provides two way to make your code work in Node.js

  1. You can export your code with Node.js as the target and it will export code that can run in Node.js
  2. The Enhanced-Require module, overloads the require function in Node.js to make webpack code work within it.

I haven’t tried either of these two systems and I’m not sure about their various limitations.

 Making a decision

Making a decision between Webpack and Browserify is more nuanced than most people think. In a feature war, Webpack does have a few features that Browserify doesn’t have. So, if you make your decisions only based on checklists of features, or if one of the features that are unique to Webpack are extremely important to you, like Hot-Loading, then Webpack is right choice for you.

If however, you’re predominantly dependent on the NPM ecosystem and you want a tool with a small and very well designed API and takes minimal configuration, you should go for Browserify. It doesn’t have all the features of Webpack, but it does have most, and it’s very easy to get started with. As an additional pro or con, depending on your philosophy, Browserify will try to push you in a certain direction regarding the modularity of your codebase. It will also make it easier to build isomorphic npm modules. With the browser field in the package.json, you can easily have modules with the same API but different implementations for Node and browser.

 My own opinion

This is a bit of a cop-out but I like both tools. I think there is a right time and place for both. In general, I prefer Browserify as it amazingly easy to get started with and plays very well with the node and npm ecosystem. I don’t see the value of requiring CSS files in my javascript usually, and images ever. That said, if a project grows very large, and I need complicated solutions that are easier with webpack, I will just transition from browserify to webpack just for that project. This I think is a great system as I get all the convention of browserify and am encouraged to keep my code extremely popular, and get to kickstart new projects with minimal configuration, but also it is extremely easy to transition from browserify to webpack when needed.

 Looking Further

With the advent of ES6, the tools of the trade are evolving. The new kid on the block is System.js (along with it’s pacakge manager jspm). System.js has a completely different approach to the problem where it’s philosophy leans mostly to ES6 compatibility, and providing a path to getting rid of bundling all together (as with HTTP 2.0/SPDY, it’s just as fast to load many smaller files as it is to load one large one). I have yet to learn much about it for now though. I’ll save it for a future blog post.

 
3,652
Kudos
 
3,652
Kudos

Now read this

Object getters and setters. And it’s many gotchas

In my previous post, I talked about how you could use Object.create() (or Object.defineProperty()) to supercharge your javascript object with unwritable properties. In this post, I’ll talk about what else is possible with Objects in ES... Continue →