Webpack is not a static site generator

I've recently used webpack for a few projects. Those were mostly static websites with a bit of interactive content. One index.html file, a few JavaScript files, and a bit of CSS on the side. You'd think that webpack has that use case figured out and backed by a solid implementation. Sadly though, none of it is true. You have to pull in so many different, slightly incompatible plugins, and write such an incredibly long webpack config file that it's not funny anymore.

Caching must not be an afterthought

Caching is something that is so fundamental that one shouldn't have to think about it. The tools we have today should do the right thing out of the box.

When it comes to static assets (images, CSS files, etc.), we shouldn't need to have a discussion whether to cache them (because the answer is always yes) or how to implement it (because the only acceptable answer here is to fingerprint the filenames with their content hash and set a far-future Cache-Control header). These options should not be configurable. If they are then users will make mistakes. There is one correct answer for each of those questions and that should be the default.

Because so many tools ignore caching or don't do it correctly (not only webpack but also for example Jekyll), I wrote mole. It does one thing, and that is convert a set of files which comprise a static website into a set which has properly fingerprinted files. That's it. Mole doesn't do fancy pre- or postprocessing, splitting or merging of files. It is a simple addition to any deployment pipeline which gives you instant benefit of fingerprinted files, regardless of the tool which you use to generate the site.

Mimic the browser, start with HTML

One big issue that webpack has is that you can't use a HTML file as an entry point. But a HTML file is exactly what a browser starts with: A browser first loads index.html, then follows all references therein. If you start with a HTML file you can construct a straightforward dependency graph.

Webpack instead starts with a JavaScript file and then magically inserts script tags into a predefined HTML file (or a global mutable state, if you will). This inverted dependency declaration makes it very hard to see what actually ends up in the HTML file.

This appears like an arbitrary restriction. There's no reason why I shouldn't be able to specify any file which webpack can process as an entry point. For example a SCSS file, if the goal is to produce a CSS file.

Everything converges towards JavaScript

With inline styles becoming more widespread, the need for external CSS files decreases. The magical extract text plugin suddenly becomes irrelevant. The only reason for external CSS files is when you have @font-face declarations. But you don't need the complicated plugin for that, simply reference the plain CSS file and optionally let mole fingerprint it. You could even put the style inline into the HTML head. If it's just one or two font-face declarations then why not?

Now that the whole static site is essentially a single HTML file and a bunch of source files compiled into a single JavaScript file, you can simplify the build pipeline even further. I'm not advocating writing plain JavaScript. The new ES6 import syntax is really nice. And I personally like TypeScript to typecheck my code. In any case the full webpack pipeline is overkill. It's much simpler to set up browserify with a few plugins (such as babel or typescript) and produce a single output file. The file you then reference from your HTML file.

The magical constraints under which Live Reload works

Webpack + React + redux were supposed to make hot code reloading a first-class citizen. However in my experience it doesn't work reliably, I can't trust it. But if I have to manually reload the website because I can't be sure whether it reloaded itself correctly then that code is useless ballast. I can just as well throw the whole hot reload code out of my pipeline.

What remains is ... not much

In the end, for the types of simple, small static webpages that I'm building, webpack is not of much help. I'm much better off with a simple browserify pipeline with TypeScript, and mole to correctly fingerprint the resulting files.