Friday, September 8, 2017

CDNs vs. bundling

Remember, this is a personal sketchbook, not a how-to guide nor really even a blog.  So I might have some bad ideas on here.  Might even be terrible.  That's ok.

I created cdnler to help me with a workflow of using Typescript, but without necessarily loading modules through npm.  If I were to use Ramda to build a site, I would load (only) Ramda's type declarations using npm, so that its classes and methods would be available to my development environment.  But on the web page itself, I'd just use a script call to a CDN.  Any project I'm working on might have 5 or 6 CDN calls on one page, and since it's best practice to use CDNs only with a local fallback, for production I'd have to download every CDN asset file by hand, and then hand-code its fallback. cdnler just does that.

Which is fine as far as that goes, but the fad these days, backed by the power of Google, is to bundle up all of your javascript into a single, or two, large, minimized files, and then link to those from within your page. This has the advantage of reducing server calls, since a script reference blocks any other browser activity until that call is resolved.  CDNs are another way of handling this bandwidth issue, since in theory, a CDN asset would be cached on the browser, and presumably shared when the same browser visits a different site with that same asset, but, to be honest, that's a bit dubious. Considering, jQuery alone, there are so many different versions, and so many different CDNs that host it, that even sites that use jQuery, and a CDN to reference it, would not necessarily be caching the same files. As well, Google now wants your site to be a progressive app, which makes CDN references problematic.  Not impossible, but the tide is against that method.

The expected way to bundle javascript code is to load of external libraries locally using a package manager like npm or yarn. Then, in the code, to require them using node.js syntax e.g.

import R = require('ramda');
and then to use a build tool like browserify or rollup which work by following all those require calls up the abstract syntax tree to know what libraries comprise the app, mushes them all into one file, which is what then goes into the <script> src reference.

Here's where my bad idea comes in.  Why not build a companion module to cdnler, that would follow all of the local script references in an html file (<script src="local.js">), then bundle and minimize those local assets?  Then it could replace those script references in the html file with a single script reference to the bundled asset. It wouldn't need to do any so-called treeshaking, just put the contents of each file in just a long file of its own.

To recap, this hypothetical work-flow would be to reference external libraries using CDNs during development, and then  download them locally during pre-build, then bundle them into a single (or more) local file during build, and then replace the CDN script references in the html with a single a reference to that local file.

What would be the point?  I just like working with CDNs.  There's something neat about having the world's javascript libraries available to just a single flat index.html. And there's something hegemonically monocultural about using npm to manage all of everyone's code.  If there's ever a problem with npm, we're all in trouble. So, it's a good thing, I think, to have a variety of ways to build and create apps.