Migrating from Jekyll to Hugo
dannyguo.com
dannyguo.com
It will soon replace an aging version of the site[3] that was built with Sitecore CMS, .NET, and SQL Server.
At first I considered using Hugo to generate the HTML for the site from git-backed JSON/YAML/TOML files. But the quantity and complexity of the Golang templates was clearly going to be tedious, inflexible, and tough to maintain.
So I settled on using Hugo to generate a read-only REST API instead[4], based on a nice blog post I had read[5][6].
This freed me to use any front-end framework I wished, and I chose Vue, Vuetify, and Axios for their simplicity and productivity on this solo-developer project.
In the end I was quite happy with this combination. Hugo was incredibly fast and productive for ranging over and manipulating all of the JSON/YAML/TOML data files to produce the final read-only REST API JSON... after the initial learning curve with Golang templates.
And the front-end really just boiled down to some key Lodash transformations of the JSON into the various shapes of data that were needed for tabular reports and Chart.js graphs.
[1] https://app.rrpm.run/ [2] https://github.com/railroadpm/site [3] http://www.railroadpm.org/ [4] https://api.rrpm.run/reports/bnsf/all [5] https://discourse.gohugo.io/t/build-a-json-api-with-hugos-cu... [6] https://forestry.io/blog/build-a-json-api-with-hugo/
Mean while the only noticable difference between the sites is the front end.
So RE: the main discussion here about Jekyll and Hugo and static site generators (SSGs), I think that if you take a moment to consider the difference between the SSG/JAMstack approach vs. the traditional "build the response on every request" back-end approach (and I'm not picking on .NET and SQL Server there, I've developed many sites using them myself) you'll see that there are some huge differences[1].
I think the most important difference is that with SSGs and JAMstack, your back-end code only runs at build time, on free build server infrastructure. There is no runtime back-end code, and therefore you can operate these JAMstack sites, at scale, at zero or near-zero operating cost. In the case of my customer, I estimate I saved them $100K over the life of this new site. Of course, your use-case must align with this sort of architecture. Not every site can or should be totally re-generated when content is changed.
And importantly for my customer, they did not have to sacrifice a nice, user-friendly content-management experience. I happen to be using Netlify CMS, but others like Contentful and Forestry are nice options too[2].
[1] https://youtu.be/uWTMEDEPw8c [2] https://headlesscms.org/
Sadly a similar thing has happened to programming languages, we use languages just for their libraries. The language itself must be treated as an empty vessel for the ML/Numeric/Web/Physics whatever it is you need. Or programmers you need to hire. This bothers me but is the purpose of our industry, to minimize construction time through reuse.
Lodash is sort of a query language for data in JavaScript. The name is a play on Underscore, the name of a rival implementation. So Lodash is literally a "lowered dash character"... i.e., an underscore.
Anyway, here's an example in the code for the website I mentioned above[1].
In this example, Lodash is wrapping a JavaScript array of objects named "rows", filtering out just the "keys" in the objects, further filtering down to only the ones that are numeric, and then mapping those to an array of strings that are properly-formatted dates.
The original array came from Hugo-generated JSON exposed as a read-only REST API[2]
[1] https://github.com/railroadpm/site/blob/master/app/component... [2] https://api.rrpm.run/reports/bnsf/current (see "rows")
I'm a big fan of serving content APIs as static assets like you are doing here. Especially good for content which changes infrequently (a few times a day rather than many times a minute).
Static site generators typically make it simple to publish a structured data view like a JSON or XML feed of content alongside content pages as HTML (such a bonus!), but it is interesting to see that you've separated the API generation entirely as a Hugo build. (presumably for compile speed?)
I work at Netlify and am something of a JAMstack enthusiast. I'd love to learn more about the experience of designing and building this. If you'd be interested in doing more of a write up, or just sharing any of the learnings from along the way, I'd love to chat.
Meanwhile the old page works perfectly.
Sure you should have your sites work without JavaScript and probably host all your fonts. I personally do that usually, but from a building standpoint, I’m assuming 3rd party fonts or forcing JavaScript for a normal site is going to be fine for more than 95% of your users.
I don't know how you feel about the GDPR (or the data brokerage industry, in general), but if web developers want to minimize government regulations we should probably architect our sites so as to minimize 3rd-party data collection of PII in the first place (which is enabled by including 3rd-party fonts).
And that you can't shell out to helper scripts makes it very restricted in so many aspects. I wanted to extract source examples from other code and preprocess it and the only way I could make it work was some really ugly go template code and that didn't even let me implement everything I want since they are so restrictive :(
I really wish one could shell out to an executable to fill the gaps.
As an example this is how code snippets are included. Sadly we cannot remove leading spaces on the lines to remove extra indentation, so now the source files look ugly :( https://github.com/actix/actix-website/blob/master/layouts/s...
And it's mainly because of Jekyll-Assets. It's just too useful for not only bundling assets but effortlessly md5 tagging everything for caching on the nginx side of things.
Hugo and others have nothing like this, and rolling your own set up isn't feasible for that because for it to be done right, it needs to be supported at the generator / plugin level so your template helpers know how to deal with looking things up from the untagged file name.
My site has about 170 blog posts and dozens of other pages and Jekyll's incremental reloader refreshes in a little over 2 seconds. That's about 1 second longer than I'd like to see a blog post get live reloaded in development, but it's good enough.
> Once that’s added the reasons to use Jekyll, which is essentially abandonware, will shrink to zero.
They are working hard on Jekyll 4.x and huge sites like Docker's documentation[0] use Jekyll. I'd still feel comfortable using it today.
It really comes down to preference IMO. Jekyll is more than adequate to use for a blog or large site. If you like liquid's template engine and enjoy having the ability to write plugins in Ruby then it's a good match.
I suspect that even if you told the browser to revalidate on each request, you would end up in situations where the browser ignores it or is overruled by a corporate proxy.
With a md5 in the URL, the browser would be forced to make a new request.
IMO max-age=0, must-revalidate is a much better choice for the average website/blog owner.
For complex apps, setting up the asset pipeline can be worth the tradeoff. But Hugo is hardly a lower tier static site generator for not supporting this.
When the content of your file changes you get a completely new file which has no cache headers associated to it. Then nginx caches the file forever, and when you make a change, a new file is created and the process repeats but if you don't make a change, then the same file is served from the user's local cache.
As someone who follows Hugo development closely, I wouldn't be surprised if both md5 tagging (fingerprinting) and sass support is out in the next week :)
See the Hugo Discourse for more details.
Could you please expand on this? This seems like something that requires a source.
It's not about a fancy asset pipeline.
It's taking app.css and turning it into app.a5fec617.css so that you can configure your web server to cache it forever. It's important to do this for CSS, JS and all of your images and other assets. Each blog post of mine has a cover image and with 170 blog posts, that's 170 blog images that need to be md5 tagged.
The asset pipeline (transforming SASS into CSS and minifying everything) is just a nice convenience.
It's also nice to be able to just write {% asset foo.jpg %} and end up with <img src="images/foo.34fbc1e9.jpg" width="256" height="256" alt="foo" /> in the HTML. Never having to manually set a height/width or alt tag (unless I want to manually override it) saves a lot of time.
If the url stays the same, you never know what version your visitors will get. You might publish a new version, but the user would not see it due to browser caches or proxies.
You are likely complacent because you're always on a good connection, since you keep arguing in these comments (even farther down) as if conditional GET requests obsolete other forms of caching.
The real benefit of ETags is that they generalize over all content dynamically, but they come at the cost of incurring more requests than expiration caching. I don't see how you could keep arguing here unless you didn't understand that trade-off.
I do cache-busting > hugo > minification using a simple bash wrapper script. Though, in the coming week, Hugo might natively start supporting the cache busting and minification.
_config_local.yml:
html_refresh: true
html_refresh_rate: 5
Then, I appended the config via: jekyll serve --config _config.yml,_config_local.yml --force-polling
And then did a check in my header include: {% if site.html_refresh %}
<meta http-equiv="refresh" content="{{ site.html_refresh_rate }}">
{% endif %}
You can find a working example in my blog's repo[1].open source headless CMS Strapi https://strapi.io and Nuxt.js frontend.
If anybody knows a python and flask based headless CMS let me know!
https://docs.google.com/presentation/d/1ZYMogOeXKCCmr7hDZnzx...
My Jekyll(Ruby) script was running over a day and never finished. Hugo(Go) ran in about 5 minutes. Granted there are over 10,000 pages being generated by Jekyll but it was so painfully slow, I couldn't possibly have a daily CI system that generated the site.
I'm still fixing some https issues with GitHub static site hosting, but it should be working soon.
I don’t care about the speed differential.
However if Hugo is actually easier somehow, well that would be tempting.
I've been using it for over two years, and this is the thing I like most about it.
In addition:
* Yes, it's super fast.
* It allows for clean layout of code with different layouts for different sections: e.g. https://github.com/hnarayanan/harishnarayanan.org
* It's got a really friendly community for support.
Where I find Hugo lacking though is I have found it very difficult to theme. Hugo has a very particular way of doing things with sections, sub-sections, leaf nodes and branch nodes, and a very particular folder structure where having an index.md file does one thing, but an _index.md file means something totally different. This would be fine if the docs were extensive and explained this clearly but they are very light in this area and most knowledge seems to be burried in individual disqus posts and other people's heads. I am sure it makes sense to people already familiar to Hugo, but trying to grok it all as a new-comer has been difficult.
As a result working out how to do even trivial things such as listings of pages in grandchild-directories, or even just having a list of child pages with other textual content has been a terrible struggle for me. Existing themes are invariably horrendously out of date, so trying to learn from those is also difficult. To this day on my site, if you go to specific directory paths there is literally a blank page because for the life of me I cannot work out how to make Hugo display just a simple list of posts in grandchild directories. It is infuriating! Perhaps it is my fault for wanting a semantic directory structure (e.g. domain.com/subject1/subject2/actualContentInHere/ and the pages for subject1/ and subject2/ are literally blank).
TL;Dr - good but if you want to do more than CSS tweaks on an existing theme then you're in for a challenge.
(Once setup though, I continue to enjoy Hugo – it’s fast and mostly stays out of one’s way.)
I still like Jekyll and I might use it for blogs that has more complex requirements for building the site. However, my blog is simple and I just wanted to generate my site quickly (and boy is it quick). Also using the template was very easy, and I was able to migrate my Jekyll theme to Hugo without too much trouble.
Hugo’s key differentiators: 1. Ease of install 2. Speed (critical for large sites) 3. Integrated live-reload while editing in near realtime 4. Multilingual capabilities 5. Flexible 6. Very strong community 7. Very good & comprehensive documentation (but not perfect…yet)
Other than 3., all other points are valid for Jekyll as well. So why move, other than for the sake of just migrating (which can be fun too...)?
But besides that Hugo is a feature rich, fast and easy to install tool.
So I created [0] Statik.
I dont mind manually building out the mardown/razor/etc. In the end, I get exactly what I want, with no overhead or heavy abstractions weghing me down.
And I don't care :)
See: https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-page...
Since you are going to spend a huge amount of time writing js code for the front-end anyways, it makes sense for the whole stack to be js.
We moved from Hugo to Gatsby for primarily this reason. I can now handover the site to js folk ...instead of having them learn golang based templates.
If you use reactjs based frameworks, you get the same amount of upfront effort as Hugo. It's not harder. However build times are slower.
But as your website complexity increases, you can leverage the reactjs ecosystem (both people and libraries). In Hugo, you get locked to their templating system. Which is nice...but very non standard and relatively non-Googleable.
If you have more than a few snippets of JS on your site, Hugo comes up way short. It's great for simple things though.
I came very close to switching to Gatsby early on, and I am very curious to know how my project[1] would have gone with Gatsby instead of Hugo.
I get the impression that for the data manipulation (avoiding complex Golang templates that generate HTML) and for build speed, Hugo takes it. Certainly if you are working in React the simplicity of a single framework is the way to go, as you did.
I also kind of felt a little more weird about mixing Gatsby and React with my preferred front-end framework, Vue, than I did about having to combine Golang template logic in one layer (API) with JavaScript in another layer (App).
In fact, I think there is value for a Gatsby built in vuejs as well .
My general goal in using an SSG is to have a static site. HTML and CSS. Maybe some images, of course. But I typically don’t reach for an SSG if I’m building something that requires a huge amount of time writing JS code. The goal is to have zero JS and zero backend. I know others may not care to create the smallest, fastest pages they can, but if I need a bunch of JS, that strikes me as the opposite of a static site.
The amount of JavaScript is not "huger" and Hugo does not make it zero markup. The only difference is that you get to leverage the react ecosystem which is far far bigger ... And it is easier for a dev (who probably already knows React) to pickup Gatsby versus Hugo.
You are in the exact same webpack, js, npm ecosystem as a vanilla react site.
If you have a fundamental distaste for js..that is a whole different matter altogether.
The first time I read about Jekyll was here, and now already something better has come along, my brain just gave me that tiny little mental high-five on my decision to no longer live on the bleeding edge
Writing in Org mode has really reduced the writing block for me. I'm so glad I switched from Octopress to Hugo about maybe 2 years back.
I used Ghost, Octopress (which was basically Jekyll), a variety of SSGs that I tested and never got to deploying, and then Pelican.
Since January 2016, though, infrastructure work basically stopped and I just write things, and occasionally dink the theme.