こんにちは、akiyamaです。
本日、アクトインディ技師部隊報告書をgithub pagesとjekyllに移行しました。
今回はなぜ移行したかと、移行作業について書きます。
・経緯
いままでのアクトインディ技師部隊報告書はCommonLisp で作られており、サーバーはunpyo、 データストアはlepisとなっています。
とてもおもしろい構成なのですが、その構成ゆえにメンテナンスコストが 特定の人にかかりがちになってしまう問題がありました。 そのことがエンジニアチームで行っている振り返りで話題となり、 今後の運用コストを下げるために別システムへ移行することになりました。
github pagesを選んだのは以下の理由からです。
- サーバーの管理が不要
- markdwonで書ける
- gitで記事が管理できる
- このブログのアイデンティティであるデザインを引き継げそう
なるべく手をかけずに管理でき、移行もプログラマブルに出来るという点を評価し決定しました。
またgithub pagesでホスティングするため、jekyll自体も出来る限り生の状態で使用することにしました。
・移行作業
次に今回の移行で対応が必要だった点を書いていきます。
・デザイン
ある種の人たちから絶賛を浴びているデザインをそのまま引き継ぐことが大前提でした。
元のシステムのソースを元に、_layout, _includeなどのファイルへ構造を移す作業でした。 ここが一番面倒だったと思います。
画像などはpublicフォルダへコピーするだけだったので簡単でした。
移行作業中にどちらの表示を見ているのかわからなくなることがあり、多少混乱しましたが、 ほぼコピーできたと思います。
・過去記事
元のシステムは先にも書きましたがCommonLisp製でデータも独自形式なので、 そのままでは扱いづらいのため、CLからJSONで出力します。
本番サーバーにデータのダンプがあるのでそれをコピーしてきます。 https://github.com/actindi-dev/tech-blog をローカルで動かし、 データベースからJSONで引っこ抜きます。
(defun to-h (post)
(let ((h (make-hash-table)))
(setf (gethash "title" h) (post-title post))
(setf (gethash "author" h) (post-author post))
(setf (gethash "date" h) (post-date post))
(setf (gethash "category" h) (post-category post))
(setf (gethash "body" h) (post-body post))
h))
(defun export-json ()
(unless *db*
(setf *db* (open-db (merge-pathnames "lepis/" *default-directory*))))
(setf posts
(loop for post in (zrang :entries 0 nil :from-end t) collect (to-h post)))
(with-open-file (out "/tmp/conv.json" :direction :output :if-does-not-exist :create :if-exists :overwrite)
(format out "~A~%" (json:encode-json-to-string posts))))
出力したJSONをmarkdownに変換します。記事の数もありますので変換スクリプトをrubyで書きます。
require 'json'
def decode_universal_time(n)
Time.at(Time.utc(1900,1,1).to_i + n)
end
json = JSON.parse(open('/tmp/conv.json').read)
json.each do |post|
date = decode_universal_time(post['date'])
fname = "_posts/#{date.strftime('%Y-%m-%d')}-#{post['date']}.markdown"
open(fname, 'w') do |out|
out.puts('---')
out.puts('layout: post')
out.puts("date: #{date.to_s}")
out.puts("title: #{post['title']}")
out.puts("author: #{post['author']}")
out.puts("categories: #{post['category']}")
out.puts("permalink: /:slug")
out.puts('---')
out.puts(post['body'].encode(universal_newline: true))
end
end
気をつける点として、外部から過去記事にはられたリンクがあるので、permalinkは維持する必要がありました。
以前のシステムではpermalinkは投稿されたUniversal time
になっています。
記事のUniversal timeを permalink: /:slug
でpermalinkに指定すれば期待したpermalinkを出力してくれます。
あとはこのスクリプトでmarkdownを生成すれば過去記事の移行は完了です。
・投稿者ページ
そのほかに対応が必要だったのは投稿者ごとのページです。 こちらの 回答を参考に投稿者ごとのStatic pageを作りました。
・paginate
jekyll3ではjekyll-paginateがgemに分離されたため、標準ではpaginateできません。 なるべく追加gemは使用しない方針でしたが、さすがにpaginateだけはインストールして使用しています。
・シンタックスハイライト
待望のシンタックスハイライト対応です。 (いままではシンタックスハイライトしたhtmlをvimなどで出力して書いていました)
_config.ymlに設定を追加して使用しています。
kramdown:
input: GFM
syntax_highlighter: rouge
現在は syntax.css のCSSを使用していまが、 ちょっと色味がきつい気がするので調整したいです。
・やっていないこと
移行しなかった部分としてはアクセスカウンターと日付の年号表記です。 年号はこのブログの雰囲気を醸し出すパーツとしては重要なのですが、 ちょっと手間が掛かりそうなので今回見送りました。
・懸念
記事ファイルが_posts/にフラットな状態で並んでしまうので、 この先件数が増えた時に管理しづらくなりそうな気がしています。
・まとめ
CommonLisp製ブログシステムからgithub pagesに移行しました。 1日程度の作業で移行できるgithub pagesはとても便利です。 後々を考えると細かいところはあまりこだわらずjekyllのデフォルトに従うほうが 将来的には楽になりそうです。
しばらく運用してみてチームメンバーの感想も聞いてみたいと思います。