Saturday, August 26, 2017

CDNs vs. Bundling and a tool to help.

When creating a website, I'm a fan of using content delivery networks (CDNs) to include libraries, over straight-up bundling all code into a single js file. That is to say, I like putting such tags into the heads of my html pages:

<script src="https://d3js.org/d3.v4.min.js"></script>
One ostensible advantage of using CDNs is to reduce bandwidth overall by caching commonly shared code on individual browsers. Rather than, say, each app loading its own version of d3, for instance, the CDN delivers the library once for each user, and each website references that same code. I imagine this would work quite well with a popular library like jQuery. Another advantage is that it allows the developer to quickly try out libraries during development without committing the time to download and configure those assets. If the idea or the library isn't working, it's easy enough to roll it back by simply deleting that <script/> tag.

However, it's a bad idea to rely on CDNs solely in production code. If the CDN is unreachable by the user, then anything that relies on that code will fail. Hosted fallbacks are important: if a src call errors out, then the browser can load that same asset from the website's server, and the user experience is unchanged. It's easy enough to do. Just follow the script with an if-then check: if the library is undefined, then load the locally hosted version. e.g:

<script type="text/javascript"> if (typeof d3== 'undefined') { document.write(unescape("%3Cscript src='/js/d3.v4.min.js type='text/javascript'%3E%3C/script%3E")); } </script>

Configuring all of this manually can be a bit of a pain, and error-prone, though.  Much easier, and this is the route many devs go, is to simply npm all libraries, roll them all up into a bundle using a task runner, and have a single script tag referencing the entire application in a single js file.  And, heck, I can't really disagree: loading-time of an app bundled like that is much less than the time to load lots of individual files.  It feels less communitarian to do it that way, as it doesn't take into account the overall time-and-bandwidth savings of using CDNs, but I get it.  It's safer.

Still, since I like the CDN approach so much, I wrote a tool to take some of the pain and risk of error out of using them.  

Cdnler is a node app that examines the <script/> tags of input html files, downloads those assets locally, and then outputs the html with altered links and fallbacks.  Basically, it does all of the above automatically.  It's a bit rough right now in the sense that its use case is exactly my own.  Within that use case it works perfectly, though.  I imagine that it could be useful even to folks who like to bundle their entire app into a locally served script, because it will automatically download all linked assets.

I'm happy to expand its usability for other developers, so if you like the idea, but it's missing some ease or usability or feature that prevents you from adopting it, please let me know what that is.