本エンジニアブログはWordPressやはてなブログではなく、独自に選定した技術スタックで構築運用しています。 ここでは、GitHubのPullRequestでMarkdownの記事の作成・レビューを行い、マージされたら自動的に公開されます。
今回は全社のエンジニアが使っているGitHubを入り口に置くことで、かなり気軽な投稿フローが構築できました。 PullRequestでの編集作業もオンラインでかなりの所まで完了するので、高効率な編集ができている実感があります。
本記事では、構築に使用した技術スタックと得られた運用フローに関してご紹介いたします。
TL;DR
- 記事はMarkdownで記述しGitHubで管理するとエンジニアネイティブ
- HTMLはHugoで生成すると、自由なカスタマイズや書きながらのローカルプレビューが便利
- ホスティングはNetlifyで行うと、GitHub連携・Hugoビルド・独自ドメインでのSSL化と配信に必要な全てをやってくれて最高
エンジニアブログの要件定義
エンジニアが書くのだから、エンジニアネイティブな色々を使って好き勝手やりたい。
この思いをもとに要件を決めました。
エンジニアネイティブなブログ運用
Web画面ポチポチで運用するのはエンジニアっぽくない。
- Markdownで書きたい!
- Gitでバージョン管理したい!
- GitHubのIssueでネタを受け付け、PullRequestで編集や校正したい!
ブログのネタ集めのハードルを下げたい
エンジニア数が増大し、多くの事業が展開されていると、会社のどこでどんな技術を使っているのか?といった情報は見えにくくなってしまいます。 各エンジニアが記事にできそうなネタを持っていても、投稿までのハードルが高いとせっかくのネタが拾えません。
運用作業を無くしたい
草の根的に有志が集って準備を始めたため、WordPressのサーバ管理などで人の仕事を増やしたくありません。
その他
- 独自ドメインでやりたい
- HTTPSでホスティングしたい
エンジニアブログの技術スタック
これらの要件を満たすブログ技術を色々と試行錯誤したどり着いた技術スタックがこちらです。
- Github: ブログの機能・デザイン・記事のコード管理
- Hugo: 静的サイトジェネレータ
- Netlify: 静的サイトビルド・ホスティング・独自ドメインSSL化
Hugoとは、オープンソースの静的サイトジェネレータで、高速性と柔軟性を特徴としています。 Go言語のhtml/templateの記法でサイトのテーマを作成し、Markdownで作成したコンテンツと結合させHTMLを作成します。類似の機能を持つ静的サイトジェネレータにはJekyllやHexoなどがあります。
Netlifyについては一言では説明しづらいのですが、非常に多機能な静的サイトのホスティングサービスです。 トップページには以下のような文言でサービス説明がなされており、モダンなWebプロジェクトの管理のためのオールインワンなワークフローを謳っています。
Build, deploy, and manage modern web projects
An all-in-one workflow that combines global deployment, continuous integration, and automatic HTTPS. And that’s just the beginning.
NetlifyはGitHubで管理されているHugoプロジェクトをビルドし、指定した独自ドメインでHTTPで公開してくれます。 ただこれだけでは語りつくせません。以降で説明するエンジニアブログの運用フローで詳細に触れます。
エンジニアブログの運用フロー
この技術スタックにより、ネタ集めから記事公開までの運用フローが全て連携できるようになりました。 ここでは、次の4つに分けて実施しているブログの運用フローを紹介します。
- GitHubのIssueでネタ集め
- Markdownで記事の執筆
- PullRequestでレビュー
master
マージで自動的に公開
GitHubのIssueでネタ集め: 社内のエンジニアに広く寄稿を募ることができる
ブログの機能・デザイン・記事は全てGitで管理しGitHubにホストしています。
リポジトリは社内のエンジニア全員がアクセス可能で、 master
以外のブランチは自由に扱えます。
また、 README.md
には下記抜粋のように、社内のエンジニア向けの執筆ガイドを準備しており、寄稿のハードルを下げています。
|
|
これを読んでGitHubにIssue登録してもらい、編集部から記事化の声掛けをしています。
Markdownで記事の執筆: ブログの完成像をローカルでプレビューできる
記事をMarkdownで書きますが、HugoがWebサーバ機能を持っており、書いている記事のブログ上での完成像をプレビューすることができます。
この情報も以下のように README.md
に執筆者向けのガイドとして記載しています。
|
|
実際、今この記事を書いている自分も hugo server
を実行し確認しながら書いています。
他ページや画像へのリンクを書いている時点で確認できるため、リンク切れやレイアウト崩れに早めに気が付くことができます。
なお、同様の運用をWordPressで実現する場合、プレビュー作成のためアカウントを執筆者用に準備する必要があります。 これは権限管理のための人の作業が発生することになります。
PullRequestでレビュー: Netlifyがプレビュー生成してくれる
PullRequestが作成・更新されると、それをトリガーとしてビルドが走り、下図のように deploy/netlify がプレビューを作成してくれます。 これが本当に便利で、このPRをマージしたらどのように本番ブログに反映されるかを予め確認できます。 また、デザイナーさんとブログのデザインを変更する際にも、作成中のデザインを実際のWeb画面で確認できるためコミュニケーションしやすくなります。
なお、PullRequestでのプレビュー生成を行うためには、リポジトリのルートディレクトリに以下のようにNetlify用のファイルを定義しておく必要があります。
参考: hugo/netlify.toml · gohugoio/hugo
|
|
master
マージで自動的に公開
PullRequestでのレビューを完了し master
へマージすると、これをトリガーとしてNetlifyによるビルドが走りブログに公開してくれます。
レビューが完了しない限りマージできませんし、レビューが完了していれば公開作業がマージボタン1つで完了します。
Netlifyに設定していれば、マージ後のビルド・デプロイ結果をSlack通知で受け取ることもできます。
感想
GitHubは毎日仕事でお世話になっていますが、HugoとNetlifyはエンジニアブログを作り始めるまで知りませんでした。
Hugoは多くの部分で自由度高くカスタマイズできるため、ブログ機能の作り込みの強い味方になりました。 Webサーバ機能によるプレビューは、ブログ機能を作り込む際にも大変役立ち、効率よく開発することができました。
Netlifyは本当に凄い。今回構築したブログの運用フローはNetlify無しにはありえません。 一定のトラフィックまでは無料で使用可能なため、エンジニアブログとは別に個人のブログもNetlifyに引越ししました。
今後は、このブログの記事をどしどし増やして、自分自身も本記事の執筆を契機にアウトプット力を上げ、会社と自分自身のエンジニアとしてのブランディングにつなげて行きたいと思います。
Appendix: Hugoによるブログ機能の作り込み実装
会社に所属する多数のエンジニアでブログを書くため、執筆者が複数人という要件のためHugo用のテーマ側で作り込んだ部分について紹介します。
TaxonomyとしてAuthorを追加
Hugoでは、デフォルトでカテゴリとタグの2つの分類(Taxonomy)を持っていますが、 config.toml
への設定により執筆者(Author)を追加しました。
|
|
これにより、記事のFrontMatterにauthorsとして以下のようにIDを指定することで、執筆者一覧ページ、執筆者個別ページが作成されます。
|
|
Hugo上の扱いでは、 [taxonomies]
に登録されているものは全てリスト形式となっています。
このため、追加した執筆者もリスト形式となっているため複数入力できてしまいます。
現状では1記事の執筆者は1名と定めているため、リストの先頭要素のみを表示するようにしています。
執筆者プロフィールを別ファイルで管理
Markdownとは別ファイルで執筆者プロフィールを管理し、記事の末尾に埋め込む仕様としました。
|
|
FrontMatterで上記のように執筆者を設定している場合、 data/authors/hashigo.toml
にTOML形式のデータファイルを記述します。
TOMLには以下のような内容を執筆者に書いてもらいます。
|
|
Hugo用のテーマでは以下のようなコードを実装しています。
|
|
first 1 $.Params.authors
でauthorsの先頭キー hashigo
を取得。
取得した値が .
で参照されるようになり、 index $.Site.Data.authors .
でデータファイルを読み込む。
「…執筆者プロフィール埋め込み…」部分では、次の指定で各プロフィール項目を埋め込み可能になります。
- 名前:
{{ $profile.name }}
- FacebookID:
{{ $profile.facebook }}
- TwitterID:
{{ $profile.twitter }}
- GitHubID:
{{ $profile.github }}
- 紹介文:
{{ $profile.bio }}
執筆者画像を別ファイルで管理
執筆者プロフィールと同様に、執筆者画像も記事の末尾に埋め込む仕様としました。
ブログデザインの変更で執筆者画像のサイズが変更になる可能性があるため、少し大きめのサイズで集めたい。 しかし、現時点のブログデザインでは80x80のサイズ指定のため、Hugoでリサイズして埋め込みたい。 Hugoにこれに対応するImage Processing機能はあるのですが、対象となる"Image"はPage Resourcesに限られており、これは各記事と同じディレクトリに置かれたファイルのみが対象でした。 これでは、記事とは別に配置した執筆者画像をリサイズできません。 この制限を回避して執筆者画像を"Image Processing"で処理できる形で取得する必要があります。
事前準備として、 content/authors/index.md
に空ファイルを準備します。
執筆者画像はこの空ファイルと同じディレクトリに content/authors/*.(jpg|png|gif)
のパスで作成します。
作成した空ファイルはHugoからは記事として扱われますので、同じディレクトリの執筆者画像は、この空ファイル記事の"Page Resources"として扱えるため、“Image Processing"で処理できる形で取得できます。
ちなみに、この空ファイル記事はURLがTaxonomyに追加したauthorsとURLが同一のため、記事一覧には表示されません。
Hugo用のテーマでは以下のようなコードを実装しています。
|
|
authorsの先頭キーを hashigo
とすると、 printf "%s.*" . | ($.Site.GetPage "page" "authors").Resources.GetMatch
にて空ファイル記事と同一ディレクトリの hashigo.*
を取得します。
HugoのImage Processingでは、画像に対してリサイズや切り取りが可能です。
$originalImage.Fit "80x80 Lanczos q90"
では、Fitにより画像を正方形に切り取り、Lanczos関数で80x80にリサイズし、画質90で保存しています。
“Image Processing"で変換した画像を <img src="{{ $image.Permalink }}" alt="{{ $profile.name }}" width="{{ $image.Width }}" height="{{ $image.Height }}">
にて埋め込むことで、変換後の画像を表示できます。