In this modern age of front-end web development we are lucky to have such a vast multitude of tools available to us. Whether that’s build tools (such as Grunt), unit test frameworks (like QUnit) or code quality tools (static analysers such as JSHint) they are all designed to make the development, deployment and maintenance process easier and faster.
There are several package management solutions available to front-end developers. A couple of the more popular ones include Bower and Component. Both work really well from a consumer point of view. Most popular packages are available through both tools so it’s quite straightforward to pick one and stick with it, adding a configuration file containing dependencies to your repository and updating your build or deployment scripts to pull them in.
For maintainers of front-end libraries this choice is not so ideal. You want to support the consumers of your library as best you can, and most of them don’t want to be stuck cloning your repository, installing your build tool of choice, figuring out how to get it to produce a single, working file and then committing that to their own repository. It’s not acceptable as a maintainer to make use of package managers during development of your library, but not to support those using your library in the same way.
So you need to publish your library to the package management registries. But which one(s) do you choose? They are all relatively popular, and all require different techniques to publish to. Component forces you to publish to GitHub (not a major concern these days, but restrictive nonetheless) and Bower forces you to commit the production-ready version of your library to the repository.
I spend a lot of time, both here at globaldev and in my personal
process. A big part of that is keeping the codebase clean and tidy. I do not
want built assets in my repository. I do not want third party assets in my
repository. It should be the job of your build and deployment tools to remove
the need for those. To support other developers with the same ethos I have to
make my libraries available through whatever tools they rely upon. The problem
is that there is no standardised solution. Some devs want to consume a
package through Bower, so you add a
bower.json file to your repository. Then
someone else wants to use Component, so you add a
component.json. Before you
know it your nice clean project is littered with configuration files and a bunch
of production-ready files that have no place in the repo.
There is a popular module available on npm, Browserify, that can be used to mitigate some of these problems. It allows you to write front-end code as Node-style modules and then bundle them up into a single file. But that single file still needs to be available somewhere as it’s not the responsibility of your consumers to produce a browser-ready build of your package.
This is where the
prepublish npm hook comes in. It allows you to add
a script that runs before your package is published to the npm registry. This
means you can Browserify and minify your script automatically, without having
built assets in the repository. This is an excellent step in the right direction
and if all of the front-end package managers offered such functionality it would
improve the situation significantly. Unfortunately, we are still left with the
problem of having to support a wide range of different tools and it’s unlikely
that everyone will abandon their chosen setup for npm.
This article may have come across as a bit of rant but I wanted to get across the difficulties surrounding front-end package management. The situation for package consumers is great. I think it’s brilliant that front-end development has all this tooling available now. But it would be even better if there could be a single standard for package publishers that didn’t tie us down to a single platform (GitHub) and doesn’t require us to commit compiled/minified code into our repositories. That may be wishful thinking but the front-end community has come up with some incredible stuff in recent years so this shouldn’t be beyond us.