Note: See also this post for why this post went away and, more to the point, why it’s back.
If you know what the JAMstack is (if you don’t, follow that link above for a much better explanation than I could give), that’s probably no big deal to you—perhaps just an alternative choice of words, right? After all, Hugo is often mentioned as part of the movement toward the JAMstack.
But there was more to it. Things were afoot. Now, you get to find out just what they were.
The fact is: this site, about to enter its second year of life, now comes to you via a different SSG—one also born in 2018, called Eleventy.
Yep, that’s what I said. Eleventy. Not Hugo any more.
Those of you who’ve been visiting this site for a while, and certainly over the last two-and-a-half months, are certainly entitled to a moment’s worth of “Whiskey Tango Foxtrot?!?” as a result of that statement. (The rest probably couldn’t care less.)
Nonetheless, I do owe you an explanation, so please return with me now to those thrilling days of yestermonth . . .
An annoying whisper
Earlier in the summer, I experimented with switching this site to Gatsby, then dropped the effort in favor of keeping this site on Hugo. I then made some pointed observations about the problems with SSGs.
That little episode had a couple of unexpected results.
First, I got a big spike in readership for that first post about it, courtesy of a retweet from the Hugo account. I remain tremendously grateful for both of those—although what I’m explaining herein likely will obviate the goodwill I received as a result, and I totally understand that.
Second, not long after I dragged my bleeding carcass away from attempting to use Gatsby without sufficient familiarity with its React framework, my initial sense of relief gave way to a distinct and annoying whisper in my ear:
“Beat you, old man. Heh, heh.”
You may recall that at least part of my interest in Gatsby in particular, and the new-gen SSGs in general, was because I wanted to amplify my coding chops—especially since working with this strain of SSGs was more likely to yield real-world experience I could use either on the current job or the next one.
Coding chops? Hah. Instead, it felt as if I were limping away while barely retaining my mouth’s choppers.
Nonetheless, I brooded over this for a few weeks until, a couple of weekends ago, I decided to take another stab at Gatsby.
Narrator: “But would he emerge alive?”
Second time’s not a charm
I didn’t need three weeks this time, as I did the first iteration, to decide it was a bad idea. After all, it had been fewer than two months since that initial attempt, so I still retained a lot of what I’d learned and, thus, avoided repeating some mistakes.
Oh, and remember what I said about struggling to figure out how to get images to appear and, once I was given a solution on Reddit, was certain it wasn’t documented in the Gatsby site? Well, I was wrong. It’s there. It’s just given the bum’s rush as an “edge case,” an “escape hatch,” as one of “a number of less common cases.” But the docs do say that one of those “less common cases” is, indeed, when:
You have thousands of images and need to dynamically reference their paths.
“Edge case,” my big, fat heinie. As if I were actually going to do an individual importation of each image, which is the Gatsby way, rather than make calls from templates to automate the process from front matter, which is the frickin’ SSG way!
Anyway, much as I’d done in early July, I got the Gatsby site tantalizingly close to what I already had on the Hugo site, but kept running into odd glitches despite my close adherence to instructions from both the documentation and numerous tutorials. I won’t bore you with the details as I did the last time. The sequence was different (although I did have more success this time with MDX files) but the overall results, and determination therefrom, were the same.
So, six days into Gatsby Experiment II, I abandoned it.
Again, I heard that whispering, snickering voice:
“Beat you again.”
But this time, I didn’t just slink off, happy to have retained my sanity if not my dignity. This time, I had a response.
“No. I rejected you.
“And now I’m going to prove that you, not I, are the problem.
“I’m going to pick the ‘new’ SSG I should’ve picked the first time."
Cast your bets
My objective remained the same as before: pick a new-gen SSG and learn. Once I clearly realized a pairing with Gatsby wasn’t for me, my research narrowed it down to two remaining contenders from among the oodles out there.
Gridsome is often described as “the Gatsby of Vue,” in that it’s as tied to the Vue framework as Gatsby is to React. The similarities were too much for me ever to give it much consideration, especially since I kept reading that you needed at least as much Vue knowledge (none of which I have) for a good experience with Gridsome as you do React knowledge (ditto, essentially) with Gatsby. Nope. Wasn’t going there, again.
That left Eleventy.
. . . and yet . . .
It doesn’t rely on a specific framework.
That last part rang especially true to me because, simply put, frameworks come and go. What are the framework-centric SSGs—and the sites built on them—going to do when those frameworks suffer their inevitable replacement by The Next Kewl Thing?
But the part that grabbed me more than anything else, and was indeed that “breath of fresh air” I’d originally hoped Gatsby would be for me, was Eleventy’s amazing flexibility. Not only does it you let choose from among multiple templating languages, but it also gives you lots of freedom in choosing the directory structure of the hosting repo and, in the end, the site that will go on the Web.
In short: within reasonable limits, Eleventy lets you build the site in a way with which you are comfortable.
SSGs like Gatsby and Gridsome are ultra-“opinionated.” They say to you, “You will do it our way, by God, and you will like it. Those are orders.”
Eleventy says, “I have some ideas but, in the end, how would you like to do it?”
If I were going to leave the comfortable confines of Hugo, it would be for Eleventy. (More about that later, under “Eleventy’s advantages.”)
However, of course, it wasn’t quite that simple.
Substituting for Hugo
As I explained back in July, Hugo comes loaded with functionality out of the box, especially since it’s several years older than the New Kewl Kids. And let me say this quite simply: I STILL recommend Hugo to less “tech-savvy” users. There’s no such thing as an SSG that “just works”—and may never be—but Hugo comes about as close for “normal” people as anything can right now.
Also, no SSG can build a site faster than Hugo can. It’s still the undisputed champ there. Fortunately, my site isn’t all that big and I don’t build it that often, so that doesn’t faze me; but anyone who wants to maintain a lot of often-changed content on an SSG is asking for trouble on anything other than Hugo. (However, Eleventy is getting there; keep reading.)
That said, I wanted to learn new stuff, so I moved on.
Yet, because of the Hugo built-ins to which I’d become accustomed, using Eleventy meant I’d have to do one of two things: (a.) give up stuff I didn’t want to lose; or (b.) learn ways to add those features to my new choice.
Again, we’re learning, here, so (b.) was the obvious selection.
So how did I make up for what Hugo does from the moment you install it? Let me explain by covering my two “must-haves”: typography and SCSS/SASS.
Definitely my type
Hugo uses the Blackfriday Markdown processor and the Chroma syntax highlighter to provide “smart” typography (curly quotation marks as well as em and en dashes), proper handling of footnotes, and appropriate formatting of code blocks.
Eleventy works with plugins, including Markdown-it plugins, to do these things. In my site’s case, I’m using
markdown-it-prism (to use PrismJS), and
I had a few (mostly self-inflicted) difficulties getting them going but the results, as you can see here and elsewhere in this site, were worth it. (Truth be known, I actually prefer how PrismJS handles code blocks over how Chroma does it in Hugo.)
In the case of Gatsby, I’d managed to get the “smart” typography and, usually, good code block formatting—but automated footnotes were glitchy and often nonfunctional (as I previously explained).
And speaking of Gatsby: while you can go through many levels of hell trying to get plugins not to FUBAR each other with Gatsby, installing and using plugins with Eleventy is ’waaaaay easier and more stable.
To enable the flexibility of SCSS/SASS, Hugo has Hugo Pipes for asset-processing—in this case, transforming one or more SCSS/SASS files on the fly while you’re developing with
Running Gulp with the settings in my repo’s
gulpfile.js file does this processing and watches constantly for changes, any of which will trigger a new processing run.
But that’s not all that this particular
gulpfile.js file does for me. It also:
Deletes the previous build—the “_site” folder—on each run to ensure that I’m looking at the latest-and-greatest.
Runs the necessary Eleventy CLI command to start up the Eleventy dev build/server process in “quiet” mode so messages aren’t so frequent.
In short, all I have to do is enter
gulp build at the command line and I’m off to the races. Gotta love it.
Now that I’ve explained some of what I had to do in Eleventy so I wouldn’t miss Hugo too badly, let me finish telling you the other side: what I like better about Eleventy. Some of this will be a little repetitive of what I said above, but I wanted it all in one place.
It’s reasonably easy to customize
If you’re gonna have to customize, which you do for any SSG (even Hugo, although not nearly as much), it’s best that it not be an awful pain. Eleventy is anything but.
I chose to use Nunjucks for my Eleventy templates, as do many Eleventy users since that seems to be the preference of Zach Leatherman himself, and have found it considerably easier to read, write, and understand than similar templating based on the Go that undergirds Hugo.
Also: while I’m mostly talking Eleventy vs. Hugo here, let me get in a particular Eleventy vs. Gatsby dig. It is vastly easier to do, say, a list of your site’s posts in Eleventy (through its collections feature) than via the impressive-but-finicky GraphQL in Gatsby (and Gridsome, for that matter).
Mind you, the Eleventy documentation (although quite good, please understand) could stand to assume a little less knowledge on the part of its potential users, as I’ve mentioned is true for all SSGs in general; but Leatherman at least includes links to quite a few Eleventy sites and, where possible, sample source code. Every time I got stuck, I spent some time poring through others’ code and, sooner or later, found an answer to a question. (To be fair, the Hugo team does this, too.)
It’s far more robust than Gatsby
I am sure that Gatsby and React adherents will hee-haw at the thought that little Eleventy is tougher than their SSG; but, in my perhaps atypical experience, it is exactly that. For someone with sharply limited free time to fool with this stuff, having an SSG that can take a few shots of PEBKAC and still (usually) hang in there is invaluable.
It’s pretty fast
It doesn’t build a site as quickly as Hugo—nothing beats Hugo on that score—but Eleventy’s build times are impressive enough for me, and I expect this aspect will improve in time, much as it did for Gatsby in going from v1 to v2.
While we’re on the subject of speed: while I was working on this post, I saw these Leatherman tweets from, respectively, his personal account and the Eleventy account:
Which has a better First Meaningful Paint time?— Zach Leatherman (@zachleat) September 6, 2019
① a raw 8.5MB HTML file with the full text of every single one of my 27,506 tweets
② a client rendered React site with exactly one tweet on it
(Spoiler: @____lighthouse reports 8.5MB of HTML wins by about 200ms)
React. Hmm. Wonder whom he might be zinging there?
Eleventy seems to handle this 30MB twitter archive JSON and output 27500 files from a single pagination template. 😅 pic.twitter.com/VTAcXU53be— Eleventy (@eleven_ty) September 7, 2019
Good job, sir. In the case of that last tweet in particular: given the Gatsby team’s continual boasting about how they can handle massive amounts of data with ease, I hope you’re making them sweat, even if just a little.
The way forward
Although I’ve made this transition, the learning experience it made possible will continue. Otherwise, there was no point to the transition.
I fully intend to stay current with both of what I now believe are the two best SSGs out there, and thus will still keep one toe in the Hugo waters, too. I’m still building the site on both Eleventy and Hugo on my local Mac and then pushing to their respective repositories on Bitbucket, GitHub, and GitLab. From there, I trigger the build at Netlify from whichever repo is appropriate. Right now, that would be the Bitbucket version of what I call
Indeed, one part of the transition was to convert all my Hugo site’s Markdown files so each file’s front matter for each SSG’s repo was interchangeable with its counterpart on the other SSG’s repo. That saves some steps. There are still some things in some posts’ main content that require specific handling for each SSG—especially when body-content images or code blocks are involved—but the posts’ front matter and purely textual parts of their body copy are now totally portable.
To put it another way: if, somewhere down the line, I decide I’d rather switch back to Hugo, I will be able to do so without a great deal of angst.
No, I don’t yet have thousands of images in this site, but I already have 'waaay too many to handle via the tedious, “one-off”-ish Gatsby process, and the number will only grow. ↩︎
I’d long wanted to learn about Gulp since I kept reading one article after another talking about its usefulness, so this was a happy coincidence for me. ↩︎
Details to come in a future post, after I’ve had more time to play with Eleventy—especially in view of some major look-and-feel changes I’m considering that would be easier thanks to this transition. (The operative word there is considering.) ↩︎
Indeed, the Straw That Broke the Camel’s Back for Gatsby Experiment II was when I couldn’t reliably make GraphQL “see” each post’s featured image as an image rather than a string, no matter how many ways I tried or how many tutorials I followed slavishly over a week’s time. And only if you can get GraphQL to “see” an image can you make Gatsby apply all the admittedly cool features available through Gatsby Image, so that’s where I drew the line the second and final time around with Gatsby. ↩︎
Another transition may be in the works on that front, too; since back before Gatsby Experiment I, I’ve been considering switching the Web’s “source of truth” for this site to either GitHub or GitLab. I can see good arguments for each, as well as for just sticking with Bitbucket, so this call remains in the air. ↩︎