Migrate to webpack, scss, and hugo #157
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I've grown disillusioned with the parcel bundler for a Rust WebAssembly purposes:
Webpack is a natural replacement for parcel, except I have a big gripe with webpack: it's configuration. I'm sure if you polled developers how they feel about webpack configuration it'd be one word: magic. I find that they are write once and cross fingers it's perfect for eternity. I'm not ok with trading one type of magic (parcel's one size fits all) for another (webpack's unintelligible config).
There are a ton of webpack intermediaries that claim a zero or simplified config: nwb, neutrino, poi but they all fell short and left a sour taste in my mouth. I spent way more time trying to simplify a webpack setup through these tools than if I had just written it myself.
This project is quite simple:
It dawned on me that no magic is needed:
wasm-pack build
ourselvesnpx tsc
ourselvesnpx webpack --mode production
ourselvesExamining the steps in closer detail:
wasm-pack build
generates a wasm bundle with typescript definitions that can be directly imported into our project.src
and outputs modern ES2017+ js (as we're relying on modern features already (ie: webassembly)) into thedist
directorydist
directory, does the one thing it does best -- bundling -- and outputs fingerprinted files to thestatic/js
directory.There are only two webpack plugins needed to accomplish this:
worker-plugin
so that webpack correctly splits the worker script into a fingerprinted file that also can correctly import a fingerprinted web assembly moduleassets-webpack-plugin
which will output a file that contains a map of original js filenames to the fingerprinted ones for a downstream process.That's it for webpack. This all can be accomplished with the shortest webpack config I've ever seen:
Now for the most opinionated part -- we'll be using the static site generator, hugo (specifically hugo extended), from here on out:
assets-webpack-plugin
(data/webpack.json
) so it can insert the fingerprinted js linksaside: the reason why we need webpack to fingerprint the js (instead of having hugo do it) is that webpack also spits out fingerprinted web worker .js and .wasm files are loaded asynchronously
In essence we'll be using a heavily simplified victor-hugo setup.
Yes it seems like overkill to introduce a static site generator for this project, but I believe it is the right approach. There is no magic glue between any of the components. Nothing really to go wrong.
I see people complain about the complexity of hugo and all the ceremony it takes to set it up but I only had to move around some files and add a single
config.toml
file. Brace yourself, it's long:Even this isn't required, but for a simple project I don't want all those extra files generated. Everything comes together with
npm run build
, which executesWebpack Config Additions
The posted webpack config is quite short, but are there other some additions that one may want to consider that hopefully won't break the "magic" barrier.
Sourcemaps
Sometimes one needs to step through JS. Without souremaps it can be difficult to reason about how the code is behaving, so we can add
devtool: "source-map"
to help set breakpoints and the like:A one line change. Everything is still reasonable. Couple things to note:
Adding sourcemaps is a well worth addition.
Ts-loader
One can consolidate the typescript then webpack invocations into the webpack config if they want to add a dash of complexity to their webpack config and add the
ts-loader
dependency. Personally, I don't see the need for this consolidation as the "simplest setup" is still far too long to be a replacement for a singletsc
command. Here is what our config would look like if we added in ts-loaderThe benefits of ts-loader:
If there was like a
new TsLoaderPlugin()
then, it would be worth considering.Dependency Analysis
While we have more dependencies specified in our
package.json
there are 3000 lines less in the lockfile.Hugo is now a required dependency, but it's widely available as a single executable.
Categorizing our dev dependencies:
The majority of them relate to testing (once jest can run the typescript compiled modules directly,
jest
will need to be the only unit testing dependency left). I'm satisfied though, I feel like I've whittled this list to down to a reasonable level. Any more would require too many hoops to jump through.