One thing led to another and I built my own static site generator today
Tags: webdev, javascript, ruby, html
Published: 2020-05-03 01:07:16

I started by building a static site as a small side project for my brother—but then I wanted partials... and regression tests. I thought partials which could help me inline the CSS and JS tags while breaking the code up into different files for organizational purposes in development. I like to inline the assets to avoid render-blocking latency on simple landing pages which will likely be served over unreliable network conditions.

At first I really didn't think I needed a generator at all, but one thing led to another and I kind built a basic one myself.

It consists of a `build.rb` file that looks like this...

```ruby
prod_build = ARGV[0] == "for_prod"

# Read files
meta_html =       File.open("workspace/meta.partial.html").read
style_css =       File.open("workspace/style.partial.css").read
body_html =       File.open("workspace/body.partial.html").read
json_data =       File.open("workspace/data.json").read
scaffold_js =     File.open("workspace/scaffold.partial.js").read
dynamic_js =      File.open("workspace/dynamic.partial.js").read
analytics_html =  File.open("workspace/analytics.partial.html").read
base_html =       File.open("workspace/base.html").read
test_html = ""

unless prod_build
  test_html = File.open("workspace/test.dev.html").read
end

# Create built page
build_string = base_html
  .gsub("{{ meta }}", meta_html)
  .gsub("{{ style }}", style_css)
  .gsub("{{ html }}", body_html)
  .gsub("{{ data }}", json_data)
  .gsub("{{ scaffold_script }}", scaffold_js)
  .gsub("{{ dynamic_script }}", dynamic_js)
  .gsub("{{ analytics }}", analytics_html)
  .gsub("{{ test }}", test_html)

# Write to target page

if prod_build
  puts "Production build.... index.html"
  File.write("index.html", build_string)
else
  puts "Development build.... wip-index.html"
  File.write("wip-index.html", build_string)
end
```

I could DRY up this code, but I prefer it to be dumb and super explicit at this stage.

As you can see, this is just basic string find and replace. `{{` could just as easily have been `💩💩` or `[cromulent >>`. It's completely arbitrary, but `{{}}` looked fancy.

`base.html` looks like this...

```html
<html lang="en">
  <head>
    {{ meta }}
    <style>
      {{ style }}
    </style>
  </head>
  <body>
    {{ html }}
    <script>
      // Data
      var data = {{ data }}

      // Code
      {{ scaffold_script }}
      {{ dynamic_script }}
    </script>
    {{ analytics }}
    {{ test }}
  </body>
</html>
```

...I even wrote my own dependency-free JavaScript test suite. I'll share more once it's further along.

I probably _should have_ reached for an existing static site generator instead of doing this from scratch, so why did I take this approach?

![](https://media3.giphy.com/media/qnE7DFFqmgdyM/giphy.gif?cid=ecf05e4701e870097f3f8d0c8ddac434302d5d1e832dd7d2&rid=giphy.gif)

In all seriousness, I generally like to avoid dependencies when doing projects like this so it's easier to hop in for a quick change in the future without having to install a bunch of old dependencies. Building a whole toolchain myself is sort of silly, but fun!

If you don't want to be like me, you may want to check out this great thread...

{% link https://dev.to/ben/what-is-the-simplest-static-site-framework-2m6k %}

Happy coding!