The Wild and Wonderful World of Static HTML Site Generators

Image result for generator

It’s a generator. You get it.

 

You ever hear a song at a party for the first time and you’re like “Man, I kinda like this song” and then you hear someone else go “Woah, retrooooo! I feel like I’m back in middle school!” and you’re like what this song is new to me.

That’s how I feel about Static HTML Site Generators. Or, to be, more accurate, that’s how I feel about the

(TM)

That’s the sort of language I’ve been hearing around HTML generators and static pages for a while now, so hey, there’s probably something to it. What are HTML generators, what are the use cases for them, and why are they becoming so popular? Let’s find out!

Review –  What Defines a Static Webpage?

If  you started programming within the last five years, odds are that you remember static webpages as something you did for the first five minutes of your bootcamp before moving onto dynamic pages and writing static off forever as something archaic to laugh at from the comfort of the future, like we do at Michael Douglas’ cellphone in Wall Street.

‘Static’ has a meaning in development besides just ‘old.’ There are 50 different definitions to distinguish between static and dynamic, but by and large the difference is that dynamic pages actually generate new HTML all on their own based on changes to their database, while static sites serve up the same HTML each time, and don’t even have a database. In short, static sites don’t have a backend. Keep this in mind – it does NOT have anything to do with animation, movement on the page, Javascript, or the lack thereof. Again, static sites can include Javascript. That’s important.

So why use static?

The thing is, dynamic web pages are super cool – they give us online shopping and user accounts and personalized content and all sorts of nifty stuff. The most magical things on the internet are done through dynamic websites and apps. BUT. Static sites are faster than dynamic sites. Much faster. You ever load a plain html file in your browser? It feels like lifting a box that you thought was pull of old kettlebells but turned out to be empty – it’s disorienting how easy it is, how quickly the page loads. And it’s way more secure. Dynamic apps, with all their forms and whatnot, have a much larger attack surface for anyone trying to hack your site.

When to use static

“But David” I hear you say. “Static web sites sound so boring. I didn’t get into development to make GeoCities sites. I want to make beautiful, exciting websites, and thinking about sticking to static makes me want to commit seppuku.” I totally understand. The interaction between users and data is a beautiful thing . But you know what else is beautiful? Single-page marketing sites with pictures, text, a ‘contact’ box and that’s it.

http://vibrant.pratheev.com/

If you’re coming from a very backend-y development education, this might not be something you focused on a lot in your education; it’s easy to hear ‘static site’ and think ‘mid-90s’, but the truth is that the people making static pages are also the people at the very forefront of pushing CSS and aesthetics in web pages to their limits.

http://portalplus.omnifi.co.uk/

Another place that devs have gotten a lot of use out of static HTML sites is as blogs, portfolios, and personal sites for themselves and for clients. Let’s be honest, do you really need a comments section on your blog? Why? So strangers can tell you that you need to learn Haskell? Come on.

Static Site Generators

Okay, so we’ve established that static web pages have the potential to be jaw-droppingly gorgeous, faster and more secure than their dynamic cousins. So what’s the problem? Just write some HTML and some CSS, throw in a bit of JS, and let’s party!

Except, as it turns out, that sucks. You write a page, you finish it, then you realize that you want to use a similar page somewhere else in your app, and that you have to copy-paste it. You do this a couple more times and before you know what happened, your code has exploded. You realize that you don’t like static sites anymore. You miss React. You start crying and ripping up your “I Heart Static Websites” t-shirt.

There, there. It’ll be okay! Know why? Because we have static site generators! Basically, what these generators do is make creating a bunch of static HTML easier without giving us an entire programming language. And boy are there lots of these things. We’ll look at a few today, but there are a bajillion of them, so feel free to explore to your heart’s delight!

Jekyll

Probably the most well known option, Jekyll is built on Ruby and geared towards blogging. Many Rails devs love it as a nice lightweight way to write a blog with all the customization that CMSes deny them, but with a nifty Templating Engine called Liquid that lets them do stuff like loop through all of their blog post files and add the files’ markup to the blog index file.

Gatsby

Gastby

Gatsby is the generator that sucked me into this rabbit hole to start with. Gatsby is a static site generator for React. What this means is that it takes Javascript files that contain React components and generates totally static HTML, CSS and JS from them. The reason this is such a big deal is that we can now make use of reusable React components on our site and move past the problem that made us cry earlier. Every ability that React gives us is now available to us, without having to pay the price of a bulky front end – everything’s static.

Conclusion

Static site generators are available for nearly every major language –  Node has Hexo, Google Go has Hugo, Python has Pelican. They generally give you a file system of some sort to start with, a place to add content (HTML), a place to specify styles(CSS), a place to create the rules of how your site gets generated(language depends on the generator), and a build tool (usually some specific command in terminal). When you run the build tool, it spits out a directory of HTML, CSS, JS and images, ready for hosting, no database or anything needed.

Particularly if you’re planning to work at an agency, there’s a high likelihood that you’re going to be doing these sorts of stylish, lightweight builds, and that you’re going to be doing them often. Invest some time in learning a static generator or two. Rebuild your personal site using it! And have fun!

Adventures in the JS Concurrency Model

Once in a while, you’ll hear a word or phrase that, if you look it up, reveals a whole new world to you. Examples include Bo-Taoshi, Flat Earth, and Battlebots. The most recent example for me was “Javascript Event Loop.” The event loop itself isn’t terribly complicated, but understanding it requires understanding basically the entire context within which Javascript gets run. So that’s what we’re learning about today! Let’s go!

Javascript differs from complied languages in that it needs a container within which to run. The container can be a browser like Chrome, or a server-side runtime like Node.js. This container splits into two parts – the engine and the runtime.

Engines

Image result for rusty engine

The job of a Javascript Engine is to compile our JS code down into a lower-level language, usually C or C++. Each of the most popular browsers in the world has its own engine which competes with the others. Chrome uses V8, Firefox uses Spidermonkey, IE uses Chakra and Safari uses JavaScriptCore. Incidentally, Spidermonkey was the first JS engine ever built, and I have to say, I think it’s pretty cool that 12 updates later it’s still in use. These engines all compile to C++, except for JavaScriptCore, which compiles to Objective-C.

Runtime Environments

Image result for web apis

The other part of the container for our JS is our runtime environment. Essentially, the job of the runtime is to provide us with JS objects and APIs that are useful and relevant to the work we might want to do in that particular context. People are often surprised by how much of the Javascript they write is not provided by the language itself, but by the runtime of the container they are using, be it a browser, Node or something else entirely. Here are some examples of functions that are provided by browsers and not the core JS language: document, XMLHttpRequest and setTimout. Again, these functions are not provided by the core Javascript language itself, but rather the runtime of whatever container wraps it.

Moving on…

As you probably know, JS is single-threaded, meaning it can only do one thing at a time. I think most of us have experienced the cognitive dissonance of holding that in mind while we somehow go ahead and do asynchronous programming anyway. The reason it’s possible is that our JS code doesn’t do all of that async stuff – our container does, which in most cases means our browser. Runtimes and the tools they provide are very context-dependent. For example, Chrome and Node.js both use the V8 engine, but while the Chrome runtime gives us access to the DOM and the window object, the Node runtime gives us require and Process. This is because Chrome, a browser, has different needs from Node, a server-side environment. So though the core language and engines are the same, the runtime environment is different, and provides different APIs.

The CallStack

You’ve probably seen the callstack in your browser’s debugger, but the details of how it works may yet elude you. In the broadest terms, the callstack shows us where we are in the execution of our program. It displays a list of callbacks, but when we look at them in the callstack, we refer to them as frames. The earlier a frame was called, the closer to the bottom of the stack it is. Every frame was  called by the one below it, except of course for the one at the very bottom. When a function on the top of the stack returns (i.e. completes), it pops off the top of the stack, leaving the one underneath is to either finish as and pop off as well or make another function call, adding a frame to the top of the stack. This goes on until the bottom frame completes and the stack clears.

Now. With async functions, it gets a little trickier. Let’s say we have an AJAX get request in our code. If it just ran in our normal code, it would block up our callstack while everything else waited for it to complete. Even mouse clicks and scroll actions would be blocked, added to a que of actions that would only affect the page once the AJAX request was complete. So these kinds of callbacks aren’t going to be part of the normal callstack. Instead, they get sent to the container’s runtime, and its web APIs assume responsibility for those async actions while the main JS code just continues on its merry way. Woohoo! Unblocked!

Okay, we sent our AJAX request through and now it’s finished! Huzzah! Okay so now what happens to the remainder of our function? Our call stack is busy with stuff, we can’t just cram it back in there all haphazard-like. No, the remainder of our async function goes to the message que.

The message que is like the waiting list to get into the callstack area. I’m calling it ‘the callstack area’ and not just ‘the callstack’ because it’s important to remember that a function can’t get into the middle or top of a callstack without being called by another function. Every frame in the callstack is being called by the frame below it, except of course the bottom frame. None of the functions in our message que will be added to an existing callstack – they’re going to start new ones. The message que is just a bunch of callbacks waiting to be the new bottom frame of the callstack.

The process that powers the movement of functions from the message cue into the callstack is called the Event Loop. The Event Loop is simply a while loop that says “While the callstack is empty, add the oldest function in the message que to the callstack as the bottom-most frame.” And thus async JS can work without blocking, and we come full circle.

Let’s take a look at a visual, courtesy of Assem Raj Baranwal to tie this all together. One part of this chart we did not discuss is called the ‘heap’ – this basically just refers to the place in our engine’s memory where our JS objects get stored. Don’t worry your little noggins too much about it this time around, we’re really just focusing on the Callstack/Message Que flow today.

Image result for js concurrency model

One thing that’s a little hard to see here is what happens when your program runs callbacks that are not Web APIs provided by the container. Do they go straight to the callstack? Nope, they just get in line at the Message Que. Any callback that fires from a click, scroll or mouse move event goes into the message que, right next to the async stuff.

So that’s the JS Concurrency Model! Fun, right? I highly suggest taking a look at Phillip Roberts’ talk about it as well. My favorite part was when we learned that XHR was just a Web API provided by browsers! This whole time! Let’s use this knowledge as a springboard to talk about more complex backend JS stuff in the future. See you next week!