Over the years, our engineering teams at HubSpot have run into issues with deploying, updating, and sharing front-end assets (e.g. Javascript, CSS, images, etc). Sure, web development has come a long way, and the latest browsers, libraries, and tools enable us to build incredibly rich and complex applications. But in many ways, webapp development is still quite young.
In particular, the tooling needed to help larger-scale development teams share front-end code and inter-operate across applications is pretty much non-existent.
It is true that we’re making progress, such as vastly improved code collaboration via Github pull requests. And the impressive surge of front-end package managers like Yeoman/Bower, npm, Jam, and Volo. These kinds of tools are great and are quickly becoming indispensable. But unfortunately, as they are right now, they still have a long way to go before they can solve some of the issues that larger-scale development teams run into, including:
So we did what any self-respecting team that discovers a new problem does, we built our own solution.
So what exactly are we talking about? It's a long story, but here's a sneak peek:
But before we get to all the details, it is worthwhile to explain why this matters. And fair warning, this will take a little while, so we've broken it up into parts:
In the beginning, most front-end development teams have one source code repository. Life is good in those days. You don't have any complicated setup scripts, dependencies are just copied right into the repository, and there is only one set of code that needs to run in production.
But those days can't last forever. As your application and development team (hopefully) grows, you'll eventually hit a point where one source repository doesn't make sense anymore. Maybe it is just for logistical reasons or maybe it is because there are too many coders stepping on each others toes (everyone loves merge conflicts!), but it eventually will happen.
I realize that there are lots of small companies that will never outgrow a single codebase and will never have have to worry about this. That's awesome, live it up! But for those of us that have to work with other people...
When you get to the point of needing two or more front-end codebases, you'll quickly end up having dependencies between them. For example, the second project might share some base styles (CSS) with the first project. Or maybe the second project uses some jQuery plugins that are defined in the first.
So what happens when those shared bits of code are updated? Do your developers realize that when they adjust the base styles in the first project, they might be breaking things in the other project? Everything might look fine when they are testing locally, but who knows what havoc it might wreck on other applications when it hits production?
You might be thinking of some ways to get around this. Why not just make a copy of the styles for each project? But all that does is just trade one problem for another. Now any updates and bug fixes that happen in one place need to be replicated. Come on, we know that's not going to happen, developers are lazy! :)
Another approach might be to refactor out all the shared pieces into another project. This does help organize things, and might help your developers realize that they need to be more careful when committing to the shared project, but it doesn't actually solve the core problem. You'll still only have a single instance of the shared assets in production. And deploying any breaking changes will require immediate updates to both dependent projects. In other words, all projects still need to move in lockstep and update as a unit (despite our initial desire to keep them separate!).
The real solution isn't copying or organization. It is versioning. Instead of forcing both projects A and B to update at the same time to keep up with changes to shared project C, let project B rely on version 1 of project C while project A updates to version 2 of project C. Since we're keeping multiple copies of project C around, A and B can stick with the old version of C and wait to be updated as needed.
The buzzword for this is dependency management.
Yes and no.
Yes, there are lots of mature dependency management solutions out there (Maven, Pip, NPM, etc). But all are primarily built to deal with the issues that arise when running code on desktops and servers. They simply weren't built to deal with browsers that are interpreting code and resolving dependencies at runtime.
Even though the core concepts are the same, dependency management of front-end assets is quite different. The web is simply a whole different ballgame:
So yeah. Even though dependency management is an established and understood practice, something new and different is needed to deal with the constraints that come with the web.
Read on to part 2 to start learning about Asset Bender—HubSpot’s tool that deals with these issues, and makes our front-end developers’ lives so much easier.