Frontend development has had an explosion of activity in the past few years with new tools and workflows coming out at a fast pace. While this rapid pace of development has lead to a lot of new productivity boosting tools and techniques, it can be dizzying to keep track of and wrap your head around all of it.

It can be tempting to just go with the first tool you find that kinda works, but there are so many different ways to do the same things and many different styles. It’s best to find a workflow that works specifically for your team and your project, as they all bring something different to the table. I cannot tell you the one workflow you should use, because each project has different requirements, so it’s better to understand for yourself the tradeoffs that different tools have in each space.

Package Managers

The traditional way of bringing in external library scripts is to just throw in a bunch of `<script>` tags with direct links to the libraries you need. As the amount of code in your application grows, this can become the source of many maintenance problems. Managing versions becomes a manual task, and that’s a pain if a library needs to be updated on multiple pages. Dependency management becomes a tangled mess that basically requires you to keep all your dependencies memorized.

Package managers are one of the best things to come out of the recent renaissance of front-end web development, as they’ve made the modularization of libraries a near standard. Better modularization has reinvigorated the front-end community by making code easier to share. With improved dependency management, individual projects can make use of more external libraries without putting a ton of extra responsibility on the user to manage them manually. Because package management is so great and has garnered so much attention, it comes with the side-effect that everyone has their own opinion on how to do it, meaning there are more options you need to learn and figure out.

Npm + Browserify

You can credit npm and Node.js for making the CommonJS style of module definition a defacto standard. CommonJS is a set of proposed specs for defining standardized ways for Javascript applications to communicate with each other, including a spec for modules. Because node and npm are built around this style of modules, all packages in the npm repository are in the CommonJS format, making interoperability very clean.

Npm was built specifically for node.js on the backend, but its massive ecosystem can be brought over to the frontend with the help of Browserify. Browserify parses your scripts for `require` statements to find dependencies, and resolves them in the same way that node.js does. After fully parsing through the dependency tree, it packages all the files into a single easy-to-use bundle, with the modules shared and encapsulated in the same way you would find in the node.js environment.

Because the ecosystem is so active, it has the largest package registry by far. Although many of these packages can only be used on the backend, Browserify provides some client-side shims for node functionality that can be emulated in the browser, enabling the use of packages developed for node on the client. By using npm on the frontend, you can easily share packages and procedures between the server and client, which depending on your use case may be a huge benefit.

The major caveat to npm’s strict approach is that in many cases, the dependency tree can quickly become bloated from deep nesting, and from dependencies that cannot be shared. These issues can lead to large packages with multiple copies of the same library supporting different dependants. If you want to take advantage of the large ecosystem of npm, you might have to give up some of the tighter bundling control and the ability to fine tune and optimize bundles that a frontend focused package manager might offer.

Bower

Bower takes more of a flexible laissez-faire approach to package management. As a result it allows for pretty much any frontend file to be included, which allows for [AMD](http://requirejs.org) (Asynchronous Module Definition) support and other files, such as css, html snippets, and even fonts and images. This gives you much more power for managing frontend projects, and lets you bring the power of package managers to all your frontend dependencies, not just javascript.

After downloading and resolving dependencies and versions, actually using the packages will be up to you. This can be a boon, or a con, as on one hand it provides more flexibility to use a bundler and workflow of your choice, but it also means you can’t just use it out of the box as well.

Component

Component is another frontend focused package manager that deals with html, css, and images, as well as javascript. The core philosophy behind Component is in creating small independent reusable components for combining into a larger project. Individual components are intended to be bundles of JS, CSS, HTML, images, and fonts, in the style that the Web Components spec will eventually take. In the future, Component envisions taking on the role of versioning and bundling Web Components, but until then, it deals with how the component packages are composed as well. Because of the unique nature in which Component works, it’s particularly good for use cases that bring together smaller bits of functionality, and not as suitable for projects based around central frameworks.

Duo

Duo is a new approach to package management that is compatible with Component. It is focused on simplicity and ease of use with less boilerplate. With Duo, all you have to do is require a github repository identifier wherever you need it inline in your Javascript, CSS, or HTML. On top of supporting Component packages, it also supports Bower packages, with future plans to support npm via browserify as well. Duo is great if your use case can get by with a lighter package manager, although if you need verbose dependency management for a complex project, its inline requires might not provide enough structure.

Other

The other package managers available tend to focus on scratching a particular itch. Jam is an AMD only package manager, and is the go-to choice for fans of AMD, which allows for asynchronous loading of code. Although its user base is much smaller, it is completely dedicated to AMD. Ender is basically a wrapper around npm, but it has the unique aspect of combining multiple micro-libraries into a jQuery like object.

Build Tools

Build tools handle the pipeline needed to transform your source files and dependencies into the final format that you want to serve to the user. This will typically involve the steps of compiling your source files (if you’re using a compile-to language), bundling your compiled sources and dependencies into a single package for the client, and minifying it, as well as other potential file transformations such as compression. Without build tools, we wouldn’t have a structured way of keeping track of these tasks and would probably resort to a messy script. Build tools are designed specifically for this purpose and have many features that would be hard to implement otherwise, as well as ecosystems that provide plugins that handle common tasks for you.

Grunt

Grunt is the godfather of node task runners, and as it has been around the longest, it also has the largest ecosystem of community provided plugins that can pretty much handle any task you might want. This heavy focus on community provided plugins is central to how you interact with Grunt. The goal is that you simply require the plugins you need, and provide minimal configuration to point them to the structure of your project, with intelligent defaults. Because plugins handle most of the complexity, what surfaces is a simple list of plugins with a configuration object.

While this works well in most cases and provides a quick and easy way to get set up quickly, as your needs become more complex and specific, it tends to lead to very large gruntfiles that use lots of plugins jerryrigged together to work with unique use cases. In these cases, setup through configuration simply isn’t powerful enough to provide clean and easily understandable build files.

Pint

Pint is built on Grunt, and tries to mitigate the issue of complex build pipelines by providing more verbose tools around specifying and organizing the dependencies of each step in the pipeline. Because you’re defining the dependencies of each step in the build process, you also get built in concurrency, which gives you much faster build times on top of a much more organized pipeline. Since Pint uses Grunt plugins, you get all this plus the benefits of a well established and well supported ecosystem.

Gulp

Gulp takes a totally different approach to build tools by putting code above configuration. Gulp plugins are thin wrappers around node’s data streams, which lead to the benefits of using Gulp. Most node tools used in build systems already use streams, as it’s the native and recommended way of dealing with data input and output in node. Because it’s the natural way of doing things in node, Gulp plugin wrappers are very simple and require little maintenance, and you can use projects that support streams without needing a plugin wrapper at all. Due to the nature of streams, build dependencies are inherently handled through piping together streams, and because build dependencies are implicit, so is concurrency. Thanks to the use of streams, build speeds are even faster than other concurrent build systems like Pint, because streams never have to output to disk IO to write to temporary files. All file manipulations are done in stream until the final write to the complete output.

Although Gulp isn’t as simple as the most basic use cases for Grunt, it’s much cleaner for use cases with interdependencies, and has an easy to learn, lightweight API that makes working with streams much easier. Gulp’s ecosystem is second to Grunt’s, and some non stream-based projects might not have a plugin yet, although they are being added at a steady rate.

Other

There are also some new upcoming build tools that look promising as well. Broccoli is a build tool that is focused on just building and not task management. It has a chaining api that focuses on directory trees instead of individual files making it very easy to set up. It also has fast file watching and rebuilding built in. Another tool, Brunch focuses specifically on building static projects, and provides an easy to use, opinionated setup.

Workflow Wrappers

Workflow wrappers bring all these tools together. If you’re new to creating projects from scratch, want to get set up faster, or just want more structure around the tools you use, workflow wrappers are intended to make that process easier for you. They provide project scaffolding which sets up the directory structure and tasks for you, along with the collection of tools you’ll need to run those tasks. They typically set up an asset pipeline including a [package manager](#package-managers), a [build tool](#build-tools), and project specific tools such as compilers, linters, minifiers, and the lot.

The key way workflow wrappers tend to differ from each other is in how opinionated they are. Some wrappers let you plug in whatever tools you want (with intelligent defaults), by getting specific workflows from the community. You can also create your own for sharing, or re-use later in another project. Other workflow wrappers provide one way to do things, but spend all their time fine tuning that workflow to provide a smoother experience.

Yeoman

The core functionality behind Yeoman is in its project generators. Generators set up your project scaffolding for you, putting together the toolset, directory structure, and anything in between. There are default official workflows provided if you’re looking for a more opinionated setup, but if those don’t fit your needs, there are over 1000 community provided generators, or you can make your own. Yeoman also provides a nice library for creating interactive scaffolding wizards, which most generators use.

Slush

Slush is designed to work with [Gulp](#gulp) in order to bring Gulp’s streaming system to scaffolding. Gulp is a streaming [build tool](#build-tool), that uses data streams to transform and manipulate files. Using streams has lots of benefits, and if you’ve bought into that style, it makes sense to use a workflow wrapper that matches. Slush is really just a thin wrapper around Gulp, but it provides a separation of concerns and a community around it. The community isn’t nearly as big as Yeoman’s, but if you want to use Gulp, it’s going to be the best tool to integrate with it. Slush is much more do-it-yourself, but by using streams, it’s a bit cleaner as well.

Codekit

Maybe you don’t have very specific needs, or you just want to get the setup out of the way so you can get straight to coding. In those cases an opinionated wrapper might be the best option. Codekit provides a more monolithic workflow that creates a singular polished experience through a fully featured GUI. Out of the box it already has many powerful features, like a build manager that lets you interactively define what files compile where, with live browser updating. It’s pretty cheap too, at only $29. That’s not as cheap as free, but if you’re developing commercially, that price is pretty much negligible.

However, while Codekit is a great tool with lots of functionality in an easy to use interface, it might not be customizable enough for more specific needs, or to adapt to an already started project. You can drop in whatever compiled language you want, but if you want to swap out other components, like using something other than bower as the package manager, you’re out of luck. The other big downside? It’s Mac only, so if your team has developers on any other OS, it probably won’t work out. Besides, some of us really like our trusty old CLI.

These workflow tools have deeply changed frontend development for the better and they’ll continue to change and evolve it in the future. With so much development going on in the community it can be hard to keep up, but the comparison pages in this article are set up to be change and updated by the community as new tools come out. If you find any of the information behind the questions could be better please go to those pages and help improve them to make sure all the tools are backed by the most accurate information. You can also email me at tim@slant.co as well.