Static Websites

A person dear to me, who is new to the tech world, asked me a simple question: "What is a static website?" It was asked in response to me saaying that I have a static website–this website you are reading.

Tech Jargon and Shibboleths

Once again it dawns on me how often jargon slips into normal conversation and acts like a shibboleth. It's hard to place one's self squarely back into the shoes of someone that has no frame of reference. If you want to get a feeling for what this is like, try to remember that at some point in your life, you would not have understood the words on this page. Even worse, you wouldn't even be learned enough determine what is a word and what is not. This is hard for you to remember because you don't–or barely–remember being illiterate. If you want a sense of that, go look at a book written in a completely different language. For example, if your first language is English, go look at a book in Hindi. I always find it fascinating, scary and humbling that I cannot tell what is a word, what is punctuation, or anything when I look at a completely different language; these new languages appear to me as tally marks as I'm certain English appears this way to a North American child.

Let's see what ChatGPT says about this.

Prompt

What does writing look like to someone that doesn't speak the language? For instance, an English speaking person who looks at Hindi for the first time. Or perhaps a 2 year old human who looks at English words in a book?

Response

To someone who doesn't speak the language, writing in an unfamiliar script can appear as a series of abstract symbols or shapes that do not have any immediate meaning or context. It may look like an intricate pattern or design, similar to how we may perceive a piece of artwork.

For example, to an English speaker who is unfamiliar with the Hindi script, the written characters may appear as a series of complex curves, lines, and dots that do not immediately convey any recognizable meaning.

Similarly, to a two-year-old child who is just learning to recognize and understand written language, English words in a book may initially appear as a collection of arbitrary shapes and lines without any inherent meaning. However, with time and exposure to the language, the child will gradually begin to recognize the patterns and associations between written symbols and spoken sounds, eventually developing the ability to read and understand written language.

That sounds about right.

Static vs Dynamic Websites

Back to static websites.

A website can either be static or dynamic. What determines its dynamism is whether code is running to generate HTML that is then returned to the user. Often the main content changes based on something like a URL, HTTP header, and so forth. The way to make a website dynamic is by having the website code make a request to a database which holds the content. Going to the same URL will often lead to the same content, but the content is pulled from another source (e.g. database). In contrast, a static website is one where the main content does not change because it is not being requested from a database or any other source. The content is transformed into HTML files and uploaded to the web server. When someone browses your website, the web browser is reading the HTML files and… well, that's it. With dynamic websites, the website code is in a programming language like PHP, Python, Ruby, Java and that language outputs HTML when a user visits your dynamic website.

So, in effect, a static website has no code that is rendering it to HTML because it is already HTML.

Dynamic Website

The following diagram illustrates the lifecycle of a single person visiting a dynamic website. It assumes that the content for the website is being pulled from a database. Regardless of whether this is true, the important part is that the majority of the time is taken up rendering the content to HTML (the "Code" column).

All the user's web browser cares about, or can even read, is HTML. So the entire purpose of the web server is to take a user's request and respond back with HTML1. It is the code's job to determine if the request is legitimate, if it is able to pull the right data, and then render all of that to HTML. It will do this for every single HTTP request.

Dynamic Website Rendering to Browsers

Static Website

A static website, on the other hand, has a much more simple workflow. There are nearly no moving parts, as the website has already been rendered to HTML. The web browser makes the request, and the web server looks up the right file and returns its HTML content to the browser. That's it.

Static Website Rendering to Browser

What's happening here is that the developer has optimized the HTML compilation step by pre-rendering all data into HTML, thereby removing the need to have code being run on every HTTP request. Since the web server was already seeded with HTML content, there is nothing for the web server to do other than return HTML to the browser.

That seeding process is what is known as "rendering" or "compilation".

So how does a static website get compiled?

A static website is often rendered during some compilation stage before deployment. The content itself can be stored anywhere, in a database or as text files on your hard drive, but the whole website can be compiled to HTML before it gets uploaded to a web server where other Internet users can visit it with their web browsers.

Static Website Compilation

For this website, all of the blog content is stored as separate Markdown files. Those files are then rendered by (at the time of writing) Middleman into a set of HTML files. If I didn't say which tool I used to render the website, there would be little to no way to tell. The rendering step can be done on my laptop, but I only use that for testing that the Markdown syntax is correct or to verify that UI changes look okay. Instead, I automated the compilation and upload step by creating a Github Actions workflow.

The Github automation watches for a merge to the master branch of the repository, then runs the Middleman render task to compile the website into HTML, then uploads the HTML files to the web server. The workflow, which takes an average of 53 seconds to complete, looks like this:

---
on:
  push:
    branches:
      - master

jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.1.2'
          bundler-cache: true
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: xxx
          aws-secret-access-key: yyy
          aws-region: us-east-1
      - name: install dependencies
        run: bundle install
      - name: build the static website
        run: make build
      - name: upload the HTML files to S3
    run: make deploy

What are the benefits and drawbacks of a static website?

Why isn't every website static? I have met a lot of people in the tech industry that don't realize their website could be static, or that the tooling exists to do this. What's funny about the situation is that static websites were how the Web was originally presented, back in the early 1990s. Then CGI came along and websites started to become more dynamic. The SaaS providers (like Wix, Squarespace, Unbounce) came along and allowed people to quickly create a website, not realizing that their mainly-static website is actually rendered as a dynamic website.

But with dynamic website, code is running. And code needs to be maintained and patched regularly. Code also has bugs in it, and those bugs could be exploited by attackers, which then could do things like dump or destroy the contents of the database that contains the website content (SQL Injection). Or perhaps to inject malicious payloads that are then rendered by the website code and displayed to visitors to a dynamic website (XSS).

Static websites optimize the HTML rendering step, since the content rarely changes. Static websites are good for blog websites, marketing websites or anything where the content doesn't change often, if at all. But not all websites work like that. Some act like applications, or present themselves as storefronts, and they need dynamism. That's fine. But not every website needs to be dynamic, so each person needs to think about the purpose of the website to help them choose which solution gives them the most features with the least maintenance.

That said, dynamic websites where some parts rarely change can also be rendered in a static way. That is what the purpose of Content Delivery Networks (CDNs) are for. They protect (for lack of a better term) a website by sitting in front of it, listening to all the browser requests. Then the CDN will proxy the HTTP request to the dynamic website and, for certain URLs, it will save the rendered HTML content in its memory. When another browser request comes along with the same URL, it will serve the rendered HTML from memory instead of proxying the request back to the dynamic website. CDNs can help save processing time and money.

Static website also require little to no maintenance. This can keeps human costs down. But since the technology behind static websites is now 30 years old, displaying static websites is cheap and easy for computers to do. Thus, static website hosting, if done right, is free. The only cost would come from a massive influx of Web traffic but, even then, the cost is small compared to having to maintain the infrastructure and code on a heavily-used dynamic website.

Appendix

Code for Sequence Diagrams

I often find that people don't realize it is easy to generate diagrams using code, instead of clicking around with a GUI. This section shows the PlantUML code I used to create each diagram.

Dynamic Website Rendering to a Web Browser

Here's the PlantUML code I used to create the sequence diagram for the dynamic website.

title Dynamic Website

participant "Web Browser" as B
participant "Web Server" as W
participant "Code" as C
participant "Database" as D

B->W: GET /blog/article
W->C: pass request to code
C->C: process request
C->D: get page content
D->C: << page text >>
C->C: gather page header, body, template
C->C: create html
C->W: << html >>
W->B: << html >>

Static Website Rendering to a Web Browser

Here's the PlantUML code I used to create the sequence diagram for the static website.

title Static Website

participant "Web Browser" as B
participant "Web Server" as W

B->W: GET /blog/article
W->B: << html >>

Static Website Compilation Step

title Static Website Compilation

participant "Developer" as D
participant "Machine" as M
participant "Code" as C
participant "Web Server" as W

D->M: compile website
M->C: render
C->C: get website template
loop each page
  C->C: render into html
end
C->C: save html into build directory
C->M: << success >>
M->W: upload html
W->M: << success >>
M->D: << success >>

Footnotes

  1. I am vastly over-simplifying here. Web browsers will want HTML, plaintext content, images (png/jpg/gif) or JSON. But for the purposes of this discussion, let's pretend they are only interested in HTML content.