Skip to content

Commit

Permalink
Merge branch 'start-migrating-to-hugo'
Browse files Browse the repository at this point in the history
We are about to embark in a major undertaking, an epic undertaking even,
seeing as it started in February 2017 with the first attempt to migrate
the site to Jekyll: #942.

The original motivation was to simplify the setup of the site: a static
site is a lot easier to manage and to develop than a Rails App. But in
October 2022, a new reason entered the fray: Heroku stopped their free
tier and ever since https://git-scm.com/ has required sponsorship whose
funding could be put to better use elsewhere.

Hence this effort was picked back up almost precisely a year ago by
Victoria Dye and myself, and we got really far, so far that pretty much
everything worked (or was at least sketched out and proven to work). The
major problem was that Jekyll required 20 minutes (!!!) just to render
the site.

Therefore we pivoted to using Hugo instead, which turned out to be a
smart choice: It takes about half a minute to render the entire site.

This topic branch starts the migration from the Rails App to a
Hugo-generated static site. The main themes of the subsequent migration
are:

- We will move the original Rails App files that contain Rails code
  mixed into HTML to `content/`, where the files defining the pages live
  in the Hugo world, then modify them to drop the Rails code and replace
  it with Hugo constructs. More often than not, we separate the commits
  that move the files from the commits that adjust the contents, to help
  Git realize that there has been a move (as opposed to a delete/add).
  This allows for noticing upstream changes that need to be reflected in
  moved & modified files when rebasing to upstream.

- In Hugo setups, the files live in the following locations:

  - `hugo.yml`

    This is the central configuration file that tells Hugo how to render
    the site.

  - `content/`

    This defines the content of the pages that are served. Only a subset
    of Hugo's functionality is available here (the idea is to leave the
    complicated stuff to the layout used to render the pages).

    Most, but not all, of the files living in this directory tree are
    HTML files that are generated (and then committed) using external
    repositories, e.g. the ProGit book and its translations.

  - `layouts/`

    This is where the "boiler plate" is defined that ties the site
    together, i.e. the header, the footer and the sidebar as well as the
    main scaffolding in which the pages' content is to be rendered.

    This is the location where most of Hugo's functionality is
    available and complex stuff can happen such as looping or accessing
    site parameters.

  - `layouts/partials/`

    This directory contains recurring templates, i.e. reusable partial
    layouts that are used to structure the elements of the site. This
    includes the side bar, how videos are rendered, etc.

  - `layouts/shortcodes/`

    This directory contains so-called "shortcodes", i.e. reusable
    elements similar to partial layouts. The major difference is that
    shortcodes can be used within `content/` while partial layouts can
    only be used from within `layouts/`.

    See https://gohugo.io/content-management/shortcodes/ for more
    information on this topic.

  - `static/`

    These files are not processed by Hugo, but copied as-are. Good for
    images, for example.

  - `assets/`

    These files are processed in specific ways. That is where the
    SASS-based style sheets live, for example.

  - `data/`

    These files define metadata that can be used in Hugo's functions.
    For example, it will contain the list of documentation categories
    that are rendered in various ways.

- In contrast to most Hugo-managed sites, we will refrain from using a
  Hugo theme, and instead stick with the existing style sheets.

  Likewise, we refrain from using Markdown at all: The existing site did
  not use it, therefore it makes little sense to start using it now.

- In addition to Hugo's directories, we also have these:

  - `script/`

    This directory contains scripts to perform recurring tasks such as
    rendering Git's manual pages into HTML that are then stored inside
    `contents/docs/`.

    For historical reasons, these are Ruby scripts for the most part, as
    it is easier to follow the development when that functionality is
    extracted from the current Rails App and turned into Ruby scripts
    that can be run stand-alone.

  - `.github/workflows/` and `.github/actions/`

    The latter directory contains a file that defines a custom GitHub
    Action that accommodates for the lack of Hugo support in GitHub
    Pages: By default, only Jekyll pages are supported out of the box,
    but Hugo sites require a custom GitHub workflow to deploy the site.

    The former directory contains files that define GitHub workflows
    that are typically run on a schedule, updating the various parts
    that are generated from external sources: the Git version, the
    ProGit Book, manual pages, etc. These workflows essentially keep the
    rendered HTML files in `content/` up to date with the respective
    external repositories.

  - `_generated-asciidoc/`

    This directory serves as a cache of "expanded AsciiDoc": many of
    Git's manual pages include content from other files, and therefore
    it is non-trivial to determine whether or not a manual page has
    changed and needs to be re-rendered (essentially, the only way is to
    expand them by inlining the `include`d files). Caching this content
    speeds up updating the manual pages drastically.

- Most of the core logic lives in `layouts/`. Hugo discerns between
  logic that is allowed in `layouts/` and logic that is allowed in
  `content/`; The latter can only access so-called "shortcodes"
  https://gohugo.io/content-management/shortcodes/. These shortcodes are
  free to use the entire set of Hugo's functionality.

  tl;dr whenever we need to do something complicated that is confined to
  only a few pages, we have to implement it in `layouts/shortcodes/` and
  insert the corresponding `{{< shortcode-name >}}` in the page itself.
  Whenever we need to something complicated that is used in more places,
  it is implemented elsewhere in `layouts/`.

- Some of the logic that cannot be performed statically (such as telling
  the user how long ago the latest macOS installer was released, or
  adjusting the Windows downloads to reflect the CPU architecture
  indicated by the current user agent) are implemented using Javascript
  instead.

- The site search needs to move to the client side, as there is no
  longer a server that can perform that functionality. Luckily, Pagefind
  (https://pagefind.app/) matured in the meantime, a very performant
  client-side search solution implemented in Javascript that relies on a
  search index that is generated at build time and that is served
  incrementally, as needed, via static files. This is what we use, then.

Signed-off-by: Johannes Schindelin <[email protected]>
  • Loading branch information
dscho committed Jul 20, 2024
2 parents fb88c03 + 28405fb commit 5d43fdb
Show file tree
Hide file tree
Showing 184 changed files with 25 additions and 5,113 deletions.
1 change: 0 additions & 1 deletion .env.example

This file was deleted.

1 change: 0 additions & 1 deletion .gemset

This file was deleted.

35 changes: 6 additions & 29 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,9 @@
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile ~/.gitignore_global

.env

# Ignore bundler config
/.bundle
/vendor/gems

# Ignore the default SQLite database.
/db/*.sqlite3*

# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
.sass-cache/

.DS_Store

#Ignore vim swpfiles
*.swp
*.swo

/public/*.zip

node_modules/

# Ignore byebug history
.byebug_history

# RSpec
spec/examples.txt
/.bundle/
/Gemfile.lock
/vendor/
/.hugo_build.lock
/public/
/resources/_gen/
1 change: 0 additions & 1 deletion .rspec

This file was deleted.

78 changes: 0 additions & 78 deletions .rubocop.yml

This file was deleted.

5 changes: 0 additions & 5 deletions .stylelintrc.json

This file was deleted.

60 changes: 0 additions & 60 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,63 +1,3 @@
# frozen_string_literal: true

source "https://rubygems.org"
ruby "3.1.3"

gem "rails", "~> 6.1"

# hacks for rails6 + ruby 3.1
gem 'net-imap', require: false
gem 'net-pop', require: false
gem 'net-smtp', require: false

gem "asciidoctor", "~> 2.0.0"
gem "elasticsearch", "2.0.2"
gem "iso8601"
gem "octokit"
gem "puma"

gem "diffy"
gem "nokogiri"
gem "rss"

# Assets
gem "sass-rails"
gem "uglifier"

group :development do
gem "awesome_print"
gem "better_errors"
gem "binding_of_caller"
gem "foreman"
end

group :development, :test do
gem "dotenv-rails"
gem "listen"
gem "pry-byebug"
gem "rubocop"
gem "rubocop-discourse"
gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rspec"
gem "ruby-prof"
gem "sqlite3"
end

group :test do
gem "database_cleaner"
gem "fabrication"
gem "factory_bot_rails"
gem "rails-controller-testing"
gem "rspec-rails"
gem "shoulda"
gem "vcr"
gem "webmock"
end

group :production do
gem "pg"
gem "rack-timeout"
gem "rails_12factor"
gem "redis-rails"
end
Loading

0 comments on commit 5d43fdb

Please sign in to comment.