tag:crieit.net,2005:https://crieit.net/tags/Hugo/feed 「Hugo」の記事 - Crieit Crieitでタグ「Hugo」に投稿された最近の記事 2020-12-22T16:15:41+09:00 https://crieit.net/tags/Hugo/feed tag:crieit.net,2005:PublicArticle/16407 2020-12-22T16:15:41+09:00 2020-12-22T16:15:41+09:00 https://crieit.net/posts/hugo-react-dev Hugo で React + TypeScript を利用してサクッとウェブサイトに RSS リーダーを追加する <p>この記事は <a target="_blank" rel="nofollow noopener" href="https://qiita.com/advent-calendar/2020/static-site-generator">Static Site Generator Advent Calendar 2020</a> 22日目の記事です。</p> <h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1> <p>Hugo のウェブサイトに組み込む RSS リーダーを TypeScript で開発してみたいと思い調査したところ、Hugo の最新版には <a target="_blank" rel="nofollow noopener" href="https://github.com/evanw/esbuild">ESBuild</a> が組み込まれていて、<strong>非常に手厚く JavaScript の開発環境がサポートされていることが分かりました。</strong> 本記事では紹介していませんが <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/hugo-pipes/babel/">Babel</a> も利用できるようです。</p> <p>また、NPM パッケージも利用できるため、普段のウェブ開発と同様の流れで開発ができ、各種ライブラリを用いた開発も非常に楽でした。<br /> 今回は Hugo で JavaScript 開発する方法を RSS リーダーの開発を例に上げ、そこで得た知見についても交える形で記事として残しておくことにしました。</p> <p><strong>ちなみに本記事内容は Hugo で JavaScript 開発する方法に焦点を絞ったものなのですが、ウェブサイトに RSS リーダーを組み込むことに焦点を絞って見たい方は <a href="#(%E4%BD%99%E8%AB%87)-rss-%E3%83%AA%E3%83%BC%E3%83%80%E3%83%BC%E3%82%92-hugo-%E3%81%AE-data-templates-%E3%81%A7%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B"><code>RSS リーダーを Hugo の Data Templates で実装する</code></a> から見ていただくことをオススメします。</strong></p> <h1 id="Hugo で JavaScript (React + TypeScript) の開発環境を整える"><a href="#Hugo+%E3%81%A7+JavaScript+%28React+%2B+TypeScript%29+%E3%81%AE%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E3%82%92%E6%95%B4%E3%81%88%E3%82%8B">Hugo で JavaScript (React + TypeScript) の開発環境を整える</a></h1> <p>まず、<strong>TypeScript のビルドは ESBuild に任せることができるため何も行う必要はありません。</strong> そのため React 開発用パッケージのインストールのみ行えば大丈夫です。</p> <p>Hugo プロジェクトのルートディレクトリで下記コマンドを実行し、<code>package.json</code> を作成してから、React の開発に必要なパッケージをインストールします。</p> <pre><code class="bash">npm init -y npm install --save react react-dom </code></pre> <p>無事パッケージのインストールが完了したら、早速 TSX ファイルを <code>assets/js/App.tsx</code> に作成してしまいます。</p> <pre><code class="javascript">// assets/js/App.tsx import * as React from "react"; import * as ReactDOM from "react-dom"; function App() { return ( <> Hello React! </> ); } ReactDOM.render( <App />, document.getElementById("react") ); </code></pre> <p>上記のコードを見てもらえば分かる通り、レンダリング先に <code>id</code> が <code>react</code> の DOM ノードを指定しています。そのため Hugo 側で該当する DOM ノードを用意する必要があります。その際の HTML テンプレートは下記になります。</p> <pre><code class="html"><!-- ... --> <!-- 利用するリソースを指定する --> <span>{</span><span>{</span> with resources.Get "js/App.tsx" <span>}</span><span>}</span> <!-- id が react の div 要素を用意する --> <div id="react"></div> <!-- TSX を ESBuild でビルドする際の Hugo のオプションを指定する --> <span>{</span><span>{</span> $options := dict "targetPath" "js/app.js" "minify" true "defines" (dict "process.env.NODE_ENV" "\"development\"") <span>}</span><span>}</span> <!-- TSX のビルドを Hugo のオプションで指定した内容で実行する --> <span>{</span><span>{</span> $js := resources.Get . | js.Build $options <span>}</span><span>}</span> <!-- 一応 SRI を有効化した状態でビルドした JS を読み込む --> <span>{</span><span>{</span> $secureJS := $js | resources.Fingerprint "sha512" <span>}</span><span>}</span> <script src="<span>{</span><span>{</span> $secureJS.Permalink <span>}</span><span>}</span>" integrity="<span>{</span><span>{</span> $secureJS.Data.Integrity <span>}</span><span>}</span>"></script> <span>{</span><span>{</span> end <span>}</span><span>}</span> <!-- ... --> </code></pre> <p>ちなみに <code>$options</code> で指定している ESBuild でビルド時に指定可能なオプションは <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/hugo-pipes/js/">Hugo の公式ページ</a> に記載されています。</p> <p>上記 HTML の記述を RSS リーダーを埋め込みたいページに追加します。<br /> この状態で該当ページにアクセスすると下記のような表示が確認できるはずです。</p> <p><img src="https://i.gyazo.com/7e196a2a52f492771deb5dd6913bbe60.png" alt="Hello React! と画面に表示される" /><br /> <strong>App.tsx で定義した内容が画面に表示される</strong></p> <p>これで React + TypeScript の開発環境が整いました。</p> <h1 id="RSS リーダーを実装する"><a href="#RSS+%E3%83%AA%E3%83%BC%E3%83%80%E3%83%BC%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B">RSS リーダーを実装する</a></h1> <p>あとは一般的な Web フロントエンド開発の流れで RSS リーダーの開発を進めていくだけです。</p> <h2 id="ウェブサイトで読み込みたい RSS フィードを準備する"><a href="#%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88%E3%81%A7%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF%E3%81%9F%E3%81%84+RSS+%E3%83%95%E3%82%A3%E3%83%BC%E3%83%89%E3%82%92%E6%BA%96%E5%82%99%E3%81%99%E3%82%8B">ウェブサイトで読み込みたい RSS フィードを準備する</a></h2> <p>RSS フィードを利用する際は必ず提供しているサービスの利用規約をご確認ください。<br /> <a target="_blank" rel="nofollow noopener" href="https://qiita.com/terms">Qiita</a> 及び <a target="_blank" rel="nofollow noopener" href="https://zenn.dev/terms">Zenn</a> については個人利用かつ自分の情報のみを扱う範囲内であれば利用が許可されているように見受けられました。</p> <p>下準備としてウェブサイトで読み込みたい RSS フィードを事前にダウンロードするためのバッチを作成します。バッチは NPM を利用して作成していきます。<strong>NPM を導入したので Hugo で利用する簡易なバッチは JavaScript でサクッと作成していきます。</strong></p> <p>まずはスクリプト作成の際に必要となるパッケージを事前にいくつかインストールします。</p> <pre><code class="bash"># html をテキスト変換にするパッケージと RSS フィードのパーサーをインストールする npm i -D --save html-to-text rss-parser </code></pre> <p>実際のコードは下記になります。ファイル名末尾が <code>.mjs</code> なのは <a target="_blank" rel="nofollow noopener" href="https://dev.to/mikeesto/top-level-await-in-node-2jad">Top-Level Await</a> を使用したいからです。</p> <pre><code class="javascript">// scripts/update-rss.mjs import { writeFileSync } from 'fs'; import pkg from 'html-to-text'; const { htmlToText } = pkg; import Parser from 'rss-parser'; const parser = new Parser(); // 自ブログで読み込みたい RSS フィードの情報を設定する const rssFeed = { Zenn: { rss_url: 'https://zenn.dev/nikaera/feed', profile_url: 'https://zenn.dev/nikaera', }, Qiita: { rss_url: 'https://qiita.com/nikaera/feed.atom', profile_url: 'https://qiita.com/nikaera', } } try { const jsonFeed = {} // RSS フィード内の description を 73字で切り取り末尾に ... を付与する関数 const spliceContent = (content) => `${htmlToText(content).slice(0, 73)}...` // rssFeed 変数で定義されてる情報を繰り返し処理する for (const [site, info] of Object.entries(rssFeed)) { // RSS フィードの URL から必要な情報を取得する const feed = await parser.parseURL(info.rss_url); // RSS フィードに登録されている項目で必要な情報のみを取得する const items = feed.items.map((i) => { return { title: i.title, content: spliceContent(i.content), url: i.link, date: i.pubDate } }) // 取得内容は jsonFeed に格納する const { rss_url, profile_url } = info jsonFeed[site] = { rss_url, profile_url, items }; } // 最後に jsonFeed に格納された内容を JSON 文字列として static/rss.json に出力する writeFileSync('./static/rss.json', JSON.stringify(jsonFeed)); } catch(err) { console.error(err); } </code></pre> <p>次に <code>package.json</code> の <code>scripts</code> に登録してコマンドとして実行可能にします。</p> <pre><code class="json">{ "scripts": { "update-rss": "node ./scripts/update-rss.mjs" } } </code></pre> <p>これで <code>npm run update-rss</code> を実行すれば自ブログで表示する際に用いる JSON ファイルとして RSS フィードの内容を <code>static/rss.json</code> に出力できます。また、JSON ファイルは <code>static</code> フォルダに出力しているため <code>http://localhost:1313/rss.json</code> でアクセスできます。</p> <p><img src="https://i.gyazo.com/508ba87c41f1c1e410b89ff1bb56be4e.png" alt="npm run update-rss を実行して出力した rss.json" /><br /> <strong>npm run update-rss を実行して出力した rss.json</strong></p> <p><img src="https://i.gyazo.com/9b7ebeedce1cb69b6b3ab8acacb0b1d1.png" alt="npm run update-rss を実行して出力した rss.json にブラウザからアクセスする" /><br /> <strong><code>http://localhost:1313/rss.json</code> にアクセスして出力した rss.json が参照可能なことを確認する</strong></p> <h2 id="RSS リーダーを React + TypeScript で実装する"><a href="#RSS+%E3%83%AA%E3%83%BC%E3%83%80%E3%83%BC%E3%82%92+React+%2B+TypeScript+%E3%81%A7%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B">RSS リーダーを React + TypeScript で実装する</a></h2> <p>準備が整ったので、早速 RSS リーダーを作成していきます。</p> <p>下記は Hugo のテーマの 1つである <a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/hugo-papermod/">hugo-PaperMod</a> の <code>archives</code> テンプレートを利用してページに埋め込むことを想定した RSS リーダーのコードです。</p> <pre><code class="typescript">// assets/js/Rss.tsx import React, { useMemo, useState } from 'react' import * as superagent from 'superagent'; const Rss = (props) => { const [feed, setFeed] = useState({}); const { name } = props; useMemo(() => { (async () => { try { const res = await superagent.get('/rss.json'); setFeed(res.body[name]); } catch (err) { console.error(err); } })() }, [name]); if (!("items" in feed)) return null return ( <div className="archive-month"> <h3 className="archive-month-header"> <a href={feed.profile_url} target="_blank" rel="noopener noreferrer">{name}</a> - <a href={feed.rss_url} target="_blank" rel="noopener noreferrer">RSS</a> </h3> <div className="archive-posts"> {feed.items.map((item) => { return <div className="archive-entry" key={item.url}> <h3 className="archive-entry-title">{item.title}</h3> <div className="archive-meta">{item.date} - {item.content}</div> <a className="entry-link" href={item.url} target="_blank" rel="noopener noreferrer">&nbsp;</a> </div> })} </div> </div> ) } export default Rss </code></pre> <p>次に <code>assets/js/App.tsx</code> で <code>assets/js/Rss.tsx</code> を読み込み画面に表示できるよう改修します。</p> <pre><code class="javascript">// assets/js/App.tsx import Rss from './Rss'; import * as React from "react"; import * as ReactDOM from "react-dom"; function App() { return ( <> <div class="archive-year"> <h2 class="archive-year-header"> Tech 🦾 </h2> <Rss name="Zenn" /> <Rss name="Qiita" /> </div> </> ); } ReactDOM.render( <App />, document.getElementById("react") ); </code></pre> <p>これで RSS リーダーを埋め込んだページを閲覧すると下記のような画面が表示されるはずです。</p> <p><img src="https://i.gyazo.com/0a6b8923d141ae70f5e298637f5acc69.png" alt="hugo-PaperMod で archives テンプレートを用いて RSS リーダーを表示する" /><br /> <strong>hugo-PaperMod で <code>archives</code> テンプレートを用いて RSS リーダーを表示したときの画面</strong></p> <p>もし他の RSS フィードを追加したい場合は <code>scripts/update-rss.mjs</code> の <code>rssFeed</code> 変数に情報を追加して、<code>App.tsx</code> に <code><Rss name="<rssFeed 変数で定義した RSS Feed 名>" /></code> を定義することで対応できます。</p> <h1 id="RSS フィードの内容を自動で更新する"><a href="#RSS+%E3%83%95%E3%82%A3%E3%83%BC%E3%83%89%E3%81%AE%E5%86%85%E5%AE%B9%E3%82%92%E8%87%AA%E5%8B%95%E3%81%A7%E6%9B%B4%E6%96%B0%E3%81%99%E3%82%8B">RSS フィードの内容を自動で更新する</a></h1> <p><code>npm run update-rss</code> を手元で実行して <code>static/rss.json</code> を更新して公開すれば、最新の RSS フィードの内容をページに反映できる状態ですが、都度手動で更新するのは面倒な作業です。</p> <p>そこで今回は GitHub Actions の <code>schedule</code> を用いて <code>static/rss.json</code> の更新を自動化します。</p> <h2 id="GitHub Actions のワークフローファイルを作成する"><a href="#GitHub+Actions+%E3%81%AE%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%95%E3%83%AD%E3%83%BC%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B">GitHub Actions のワークフローファイルを作成する</a></h2> <p>実際のワークフローファイルは下記になります。<code>schedule</code> の項目で設定している内容がワークフローの実行スケジュールになります。今回は半日毎に更新が走るようにしました。</p> <pre><code class="yml"># .github/workflows/update-rss.yml name: update rss json file on: push: branches: - main # Set a branch name to trigger deployment schedule: - cron: '0 */12 * * *' # 今回は半日に 1回のタイミングで更新するようにした jobs: build: runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 with: ref: main submodules: true # Fetch Hugo themes (true OR recursive) fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod - name: Use Node.js 14.10.1 uses: actions/setup-node@v1 with: node-version: 14.10.1 - name: Install dependencies run: npm install - name: Update RSS Feeds run: npm run update-rss - name: Commit files run: | git config --local user.email "[email protected]" git config --local user.name "GitHub Action" git add static/rss.json STATUS=$(git status -s) if [ -n "$STATUS" ]; then git commit -m "Update rss.json `date +'%Y-%m-%d %H:%M:%S'`" -a git push origin main fi </code></pre> <p>上記ワークフローファイルをプロジェクトに追加して、リモートリポジトリにプッシュした後は、ワークフローが実行されるタイミングを待ちます。</p> <p>無事にワークフローの実行が完了すると下記のようなコミットが追加されているはずです。</p> <p><img src="https://i.gyazo.com/ebb7cb2e64b13e4a1e1a592836f511f5.png" alt="GitHub Actions が JSON ファイルを更新してコミットしている" /><br /> <strong>GitHub Actions が JSON ファイルを更新してコミットしている</strong></p> <p><img src="https://i.gyazo.com/1a74399a3cf1053e0480a01590086fbe.png" alt="コミットの詳細を見ると正常に JSON ファイルが更新されていることを確認できる" /><br /> <strong>コミットの詳細を見ると正常に JSON ファイルが更新されていることが確認できる</strong></p> <p><img src="https://i.gyazo.com/bf86668d5fc32ca09b6d2cfcf71262ce.png" alt="コミット後 Hugo をビルド & デプロイするとページが更新されていることを確認できる" /><br /> <strong>コミット後 Hugo をビルド & デプロイするとページが更新されていることを確認できる</strong></p> <p>これで Zenn や Qiita 等に記事を書いた際に、都度手動で <code>static/rss.json</code> を更新してページに最新の内容を反映させる作業は必要なくなりました。</p> <h1 id="(余談) RSS リーダーを Hugo の Data Templates で実装する"><a href="#%28%E4%BD%99%E8%AB%87%29+RSS+%E3%83%AA%E3%83%BC%E3%83%80%E3%83%BC%E3%82%92+Hugo+%E3%81%AE+Data+Templates+%E3%81%A7%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B">(余談) RSS リーダーを Hugo の Data Templates で実装する</a></h1> <p>ちなみに Hugo には <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/templates/data-templates/">Data Templates</a> という仕組みがあり、これを用いることで実は JavaScript を利用しなくても HTML テンプレートで RSS リーダーを実現できるということを後から知りました。</p> <p>そこで最後に Data Template での RSS リーダーの実装方法について記載します。</p> <p>まずは、<code>scripts/update-rss.mjs</code> の内容を書き換えます。</p> <pre><code class="typescript">// scripts/update-rss.mjs import { writeFileSync } from 'fs'; import pkg from 'html-to-text'; const { htmlToText } = pkg; import Parser from 'rss-parser'; const parser = new Parser(); const rssFeed = { Zenn: { rss_url: 'https://zenn.dev/nikaera/feed', profile_url: 'https://zenn.dev/nikaera' }, Qiita: { rss_url: 'https://qiita.com/nikaera/feed.atom', profile_url: 'https://qiita.com/nikaera' } } try { const jsonFeed = {} const spliceContent = (content) => `${htmlToText(content).slice(0, 73)}...` for (const [site, info] of Object.entries(rssFeed)) { const feed = await parser.parseURL(info.rss_url); const items = feed.items.map((i) => { console.log(i); return { title: i.title, content: spliceContent(i.content), url: i.link, date: i.pubDate } }) const { rss_url, profile_url } = info jsonFeed[site] = { rss_url, profile_url, items }; /* 最終的な JSON ファイルの出力先は data フォルダとなり、RSS フィード毎に出力する 例: ./data/Qiita.json, ./data/Zenn.json, etc. */ writeFileSync(`./data/${site}.json`, JSON.stringify(jsonFeed[site])); } } catch(err) { console.error(err); } </code></pre> <p>上記を実行することで <code>data/Qiita.json</code> や <code>data/Zenn.json</code> にファイルが出力されます。</p> <p>Hugo の Data Template を用いると <code>data</code> フォルダ内に配置した <code>json</code>, <code>yaml</code>, <code>toml</code> 形式のファイルは Go の HTML テンプレートで読み込めるようになります。</p> <p>例えば、<strong><code>data/Qiita.json</code> に配置された JSON ファイルを読み込みたい場合は Go のテンプレートで <code>$Qiita := $.Site.Data.Qiita</code> のような記述でできます。</strong></p> <p>次に RSS リーダーを埋め込んでいたページを下記のように書き換えます。</p> <pre><code class="html"><!-- ... --> <!-- React 関連の記述を全て削除する --> <!-- <span>{</span><span>{</span> with resources.Get "js/App.tsx" <span>}</span><span>}</span> <div id="react"></div> <span>{</span><span>{</span> $options := dict "targetPath" "js/app.js" "minify" true "defines" (dict "process.env.NODE_ENV" "\"development\"") <span>}</span><span>}</span> <span>{</span><span>{</span> $js := resources.Get . | js.Build $options <span>}</span><span>}</span> <span>{</span><span>{</span> $secureJS := $js | resources.Fingerprint "sha512" <span>}</span><span>}</span> <script src="<span>{</span><span>{</span> $secureJS.Permalink <span>}</span><span>}</span>" integrity="<span>{</span><span>{</span> $secureJS.Data.Integrity <span>}</span><span>}</span>"></script> <span>{</span><span>{</span> end <span>}</span><span>}</span> --> <div class="archive-year"> <h2 class="archive-year-header"> Tech 🦾 </h2> <div class="archive-month"> <!-- data/Zenn.json の内容を読み込む --> <span>{</span><span>{</span> $Zenn := $.Site.Data.Zenn <span>}</span><span>}</span> <h3 class="archive-month-header"> <a href="<span>{</span><span>{</span> $Zenn.profile_url <span>}</span><span>}</span>" target="_blank" rel="noopener noreferrer">Zenn</a> - <a href="<span>{</span><span>{</span> $Zenn.rss_url <span>}</span><span>}</span>" target="_blank" rel="noopener noreferrer">RSS</a> </h3> <div class="archive-posts"> <!-- 配列で格納されている記事情報を繰り返し処理で取得する --> <span>{</span><span>{</span>- range $Zenn.items <span>}</span><span>}</span> <div class="archive-entry" key="<span>{</span><span>{</span> .url <span>}</span><span>}</span>"> <h3 class="archive-entry-title"><span>{</span><span>{</span> .title <span>}</span><span>}</span></h3> <div class="archive-meta"><span>{</span><span>{</span> .date <span>}</span><span>}</span> - <span>{</span><span>{</span> .content <span>}</span><span>}</span></div> <a class="entry-link" aria-label="<span>{</span><span>{</span> .content <span>}</span><span>}</span>" href="<span>{</span><span>{</span> .url <span>}</span><span>}</span>" target=" _blank" rel="noopener noreferrer"></a> </div> <span>{</span><span>{</span>- end <span>}</span><span>}</span> </div> </div> <div class="archive-month"> <!-- data/Qiita.json の内容を読み込む --> <span>{</span><span>{</span> $Qiita := $.Site.Data.Qiita <span>}</span><span>}</span> <h3 class="archive-month-header"> <a href="<span>{</span><span>{</span> $Qiita.profile_url <span>}</span><span>}</span>" target="_blank" rel="noopener noreferrer">Qiita</a> - <a href="<span>{</span><span>{</span> $Qiita.rss_url <span>}</span><span>}</span>" target="_blank" rel="noopener noreferrer">RSS</a> </h3> <div class="archive-posts"> <!-- 配列で格納されている記事情報を繰り返し処理で取得する --> <span>{</span><span>{</span>- range $Qiita.items <span>}</span><span>}</span> <div class="archive-entry" key="<span>{</span><span>{</span> .url <span>}</span><span>}</span>"> <h3 class="archive-entry-title"><span>{</span><span>{</span> .title <span>}</span><span>}</span></h3> <div class="archive-meta"><span>{</span><span>{</span> .date <span>}</span><span>}</span> - <span>{</span><span>{</span> .content <span>}</span><span>}</span></div> <a class="entry-link" aria-label="<span>{</span><span>{</span> .content <span>}</span><span>}</span>" href="<span>{</span><span>{</span> .url <span>}</span><span>}</span>" target=" _blank" rel="noopener noreferrer"></a> </div> <span>{</span><span>{</span>- end <span>}</span><span>}</span> </div> </div> </div> <!-- ... --> </code></pre> <p>また GitHub Actions のワークフローを用いて RSS フィードの情報を更新していた場合は、<code>.github/workflows/update-rss.yml</code> ファイルの更新も必要になります。</p> <pre><code class="yml"># .github/workflows/update-rss.yml name: update rss json file on: push: branches: - main # Set a branch name to trigger deployment schedule: - cron: '0 */12 * * *' jobs: build: runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 with: ref: main submodules: true # Fetch Hugo themes (true OR recursive) fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod - name: Use Node.js 14.10.1 uses: actions/setup-node@v1 with: node-version: 14.10.1 - name: Install dependencies run: npm install - name: Update RSS Feeds run: npm run update-rss # Git で追加する内容を data フォルダに変更する # git add static/rss.json -> git add data/ - name: Commit files run: | git config --local user.email "[email protected]" git config --local user.name "GitHub Action" git add data/ STATUS=$(git status -s) if [ -n "$STATUS" ]; then git commit -m "Update data folder `date +'%Y-%m-%d %H:%M:%S'`" -a git push origin main fi </code></pre> <p>これで JavaScript で作成した RSS リーダーから、Hugo の Data Templates を用いて作成した RSS リーダーへ移行できました。</p> <h1 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h1> <p>Hugo で React + TypeScript 開発を楽にできそうなことが分かり、テンションが上がってしまい、そのままのノリで実際に RSS リーダーを自ブログ向けに作成してみました。</p> <p>しかし、本記事内容で RSS リーダーを実装するのであれば、Hugo の Data Templates を利用することがベストなことに後から気づきました。ただ Hugo での JavaScript を用いた開発手法が理解でき勉強になったので結果ヨシとしました。</p> <p>Hugo での JavaScript 開発環境は相当充実していることが分かったので、また何かアイデアを思いついたら気軽に作って自ブログに取り込んでいきます。今はザックリ WebGL/WebVR とかで何か面白いもの作れそうだなと考えています。</p> <h1 id="参考リンク"><a href="#%E5%8F%82%E8%80%83%E3%83%AA%E3%83%B3%E3%82%AF">参考リンク</a></h1> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://esbuild.github.io/">esbuild - An extremely fast JavaScript bundler</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/templates/data-templates/">Data Templates | Hugo</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/functions/">Functions Quick Reference | Hugo</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/hugo-pipes/js/">JavaScript Building | Hugo</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://reactjs.org/docs/hooks-intro.html">Introducing Hooks – React</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/rbren/rss-parser">rbren/rss-parser: A lightweight RSS parser, for Node and the browser</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/html-to-text/node-html-to-text">html-to-text/node-html-to-text: Advanced html to text converter</a></li> </ul> nikaera tag:crieit.net,2005:PublicArticle/16323 2020-12-10T00:55:08+09:00 2020-12-10T00:59:23+09:00 https://crieit.net/posts/hugo-github-actions-for-github-pages Hugo + GitHub Pages + GitHub Actions で独自ドメインのウェブサイトを構築する <h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1> <p><img src="https://i.gyazo.com/ffe8fe276b9d008461880581002430ec.png" alt="Hugo のトップページ" /></p> <p>Zenn や Qiita, note など様々なウェブサービスで記事を書くにつれて、ふと雑多な内容で自分の好き勝手に記事を書いて公開できる自分のブログが欲しくなりました。そこで、自分のブログを作ろうと思い調査したところ、SSG で作るのが手っ取り早そうだったのと、その中でも一番ラクにウェブサイトが構築できそうな <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/">Hugo</a> を採用しました。</p> <p>また、デプロイは簡単に行いたかったので、デプロイ先として <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/about-github-pages">GitHub Pages</a> を採用しました。<br /> 独自ドメインの割り当てから HTTPS 対応まで無料でできるかつ、使い慣れている GitHub をデプロイ先に使えることが決め手でした。</p> <p>Hugo で自分のブログを構築して GitHub Pages で公開できるようになったのですが、ブログ内容を更新したり記事を書くたびにビルドしてデプロイをするのが、意外と面倒なことに気づきました。そこで、<a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action">GitHub Pages action</a> を用いて、ビルドしてデプロイするという作業は自動化しました。</p> <p>上記までの作業をすることで、自分のブログを書いたり更新することだけに集中できる環境を整えることができました。ウェブサイトを作りこむ以外は、簡単ないくつかの作業をするだけで Hugo で満足のいく自分のブログを書く環境が整えられたので、その手順についてまとめてみました。</p> <p>ちなみに本記事の手順で実際に作成した私のブログは下記です。<br /> <a target="_blank" rel="nofollow noopener" href="https://nikaera.com/">https://nikaera.com/</a></p> <h1 id="Hugo を PC にインストールする"><a href="#Hugo+%E3%82%92+PC+%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B">Hugo を PC にインストールする</a></h1> <p>私は Windows には <a target="_blank" rel="nofollow noopener" href="https://chocolatey.org/">Chocolatey</a>、Mac では <a target="_blank" rel="nofollow noopener" href="https://brew.sh/index_ja">Homebrew</a> で Hugo をインストールしました。Chocolatey や Homebrew を利用したインストール方法については <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/getting-started/installing/">公式サイトの手順</a> で公開されています。</p> <pre><code class="bash"># Mac で Homebrew を使って Hugo をインストールする brew install hugo </code></pre> <pre><code class="powershell"># Windows で Chocolatey を使って Hugo をインストールする choco install hugo -confirm # Sass/SCSS を用いてウェブサイトのデザイン改修を行いたい場合は # 下記で Chocolatey を使って Hugo をインストールする choco install hugo-extended -confirm </code></pre> <h1 id="Hugo で自分のウェブサイトを構築する"><a href="#Hugo+%E3%81%A7%E8%87%AA%E5%88%86%E3%81%AE%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E6%A7%8B%E7%AF%89%E3%81%99%E3%82%8B">Hugo で自分のウェブサイトを構築する</a></h1> <h2 id="Hugo プロジェクトを作成する"><a href="#Hugo+%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B">Hugo プロジェクトを作成する</a></h2> <p>下記コマンドで Hugo のプロジェクトフォルダを生成できます。</p> <pre><code class="bash">hugo new site <プロジェクトフォルダのパス> </code></pre> <p>Hugo のコンフィグファイルのデフォルトフォーマットは <a target="_blank" rel="nofollow noopener" href="https://github.com/toml-lang/toml.io/blob/main/specs/ja/v1.0.0-rc.2.md">TOML</a> 形式なのですが、<code>hugo new site <プロジェクトフォルダへのパス> -f json</code> のように <code>-f</code> オプションを付与することで JSON フォーマットでもコンフィグファイルを生成可能です。</p> <p>後述しますが、一部の Hugo のテーマはコンフィグファイルのサンプルが JSON ファイルで書かれています。その場合は、新規で設定するコンフィグファイルのフォーマットも JSON で統一しておくと各種設定項目の調整が楽になりそうです。</p> <p>もしくは<a target="_blank" rel="nofollow noopener" href="https://github.com/sclevine/yj">こちら</a>のようなコンバーターを使用したり、<a target="_blank" rel="nofollow noopener" href="https://pseitz.github.io/toml-to-json-online-converter/">こちら</a>のようなウェブのコンバーターを使用して、設定ファイルを JSON から TOML フォーマットに変更しても良さそうです。</p> <h2 id="ウェブサイトのテーマを探す"><a href="#%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88%E3%81%AE%E3%83%86%E3%83%BC%E3%83%9E%E3%82%92%E6%8E%A2%E3%81%99">ウェブサイトのテーマを探す</a></h2> <p>テーマとは、ウェブサイトのデザインテンプレートのことです。テーマは <a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/">Hugo Themes</a> で公開されているので、この中から自分の好みを選びます。Hugo ではテーマの内容をカスタマイズしたり差し替えることもできるので、あとから一部デザインを自分好みに修正できます。</p> <p><img src="https://i.gyazo.com/294b076125052fe8bd9574c5bd0d1f0b.png" alt="Hugo Themes にアクセスした時のページ" /><br /> <strong><a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/">Hugo Themes</a> にアクセスした時のページ</strong></p> <p>お気に入りのテーマが見つかったら、<code>Download</code> ボタンをクリックしてテーマの GitHub URL を控えておきます。</p> <p><img src="https://i.gyazo.com/36ce79358e416ff6c92e7ad405c2abfa.png" alt="Kiera というテーマのページ" /><br /> <strong><a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/hugo-kiera/">Kiera</a> というテーマのページ</strong></p> <h2 id="Hugo プロジェクトにテーマを適用する"><a href="#Hugo+%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E3%83%86%E3%83%BC%E3%83%9E%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B">Hugo プロジェクトにテーマを適用する</a></h2> <p>テーマの適用方法については <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/getting-started/quick-start/#step-3-add-a-theme">公式サイトの手順</a> で紹介されていますが、Hugo のプロジェクトフォルダのルートで下記コマンドを実行して、コンフィグファイルに <code>theme</code> を追記するだけです。</p> <pre><code class="bash">git clone <テーマの GitHub URL> themes/<テーマ名> --depth=1 echo 'theme = "<テーマ名>"' >> config.toml </code></pre> <p>どのテーマも基本的に適用方法は同じで、例えば私が採用したテーマである <a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/hugo-papermod/">PaperMod</a> を適用する場合は下記コマンドを実行することになります。</p> <pre><code class="bash">git clone https://github.com/adityatelange/hugo-PaperMod themes/hugo-PaperMod --depth=1 echo 'theme = "hugo-PaperMod"' >> config.toml </code></pre> <p>これで自分のウェブサイトを作り込んでいくための準備が整いました。</p> <h2 id="ウェブサイトを作り込む"><a href="#%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E4%BD%9C%E3%82%8A%E8%BE%BC%E3%82%80">ウェブサイトを作り込む</a></h2> <p><strong>各テーマには <code>exampleSite</code> というウェブサイト作成の参考になる Hugo のプロジェクトフォルダが存在します。</strong> 最初は <code>exampleSite</code> フォルダ内に存在する各種ファイルを自分のプロジェクトにコピー&ペーストして、改変しながらウェブサイトを作り込んでいくとスムーズに作業が進められます。</p> <p><code>exampleSite</code> フォルダは大抵 GitHub プロジェクトのルートに存在しているのですが、<strong>GitHub のブランチで管理しているものもあります。</strong> 私の採用した PaperMod は GitHub の <code>exampleSite</code> ブランチで管理していました。</p> <p>上記のような詳細は Hugo のテーマページに記載があるはずなので、事前に <code>exampleSite</code> フォルダが配置されている場所や設定可能な項目等をチェックしておくことをオススメします。実際のウェブサイトの見た目を確認するには、Hugo のプロジェクトフォルダのルートで下記コマンドを実行します。</p> <pre><code class="bash">hugo server </code></pre> <p><code>hugo server</code> 実行中に、ウェブサイトの設定を変更したり記事を追加すると、自動的にビルドが実行されるので常に最新のウェブサイトの見た目を確認できます。また、その際にエラーもコンソールに出力されるので、適宜修正しながらウェブサイトの作成を進めていくことが可能です。</p> <h1 id="GitHub にデプロイ環境を整える"><a href="#GitHub+%E3%81%AB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E7%92%B0%E5%A2%83%E3%82%92%E6%95%B4%E3%81%88%E3%82%8B">GitHub にデプロイ環境を整える</a></h1> <p>ウェブサイトの構築が出来ればあとはデプロイするだけです。今回は GitHub Actions でデプロイするため、残りの作業は GitHub 上で進めていきます。一応 GitHub Actions を使わずに手動でデプロイする手順については、Hugo の <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/hosting-and-deployment/hosting-on-github/">公式サイトの手順</a> にて紹介されています。</p> <p>GitHub Actions を用いてデプロイできるようにした際の利点としては下記があります。</p> <ul> <li>デプロイ時に毎回手動で複数コマンド実行する手間が省ける</li> <li>自動化することでデプロイ時のコマンドミスを防ぐことが可能</li> <li><strong>常に統一した Hugo のビルド環境が利用可能</strong></li> </ul> <p>最初のうちは私も公式サイトの手順通りに Mac で手動デプロイしていました。しかし、Windows 環境でデプロイ作業した際、本番環境デプロイ時に <a target="_blank" rel="nofollow noopener" href="https://gohugo.io/hugo-pipes/fingerprint/">SRI</a> 関連のエラーが発生してしまい、ウェブサイトに stylesheet が適用されないバグが発生してしまいました。</p> <p>結局原因はよく分からなかったのですが、GitHub Actions 経由でデプロイするようにしたところ直りました。<strong>CI 経由でデプロイできるようになると、こういった実行環境の違いによる挙動も気にする必要が無くなります。</strong></p> <p>一応 Windows 環境で発生した SRI 関連のバグは Hugo で該当するテンプレートファイルを <code>layouts</code> フォルダを利用して差し替えて、integrity の設定内容を空にすることで、本番環境でも stylesheet が適用できるようになったことは確認しました。<a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/a/65052963">詳細はこちら</a>。</p> <h2 id="自分のウェブサイトをデプロイするためのリポジトリを作成する"><a href="#%E8%87%AA%E5%88%86%E3%81%AE%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B">自分のウェブサイトをデプロイするためのリポジトリを作成する</a></h2> <p>GitHub の <a target="_blank" rel="nofollow noopener" href="https://pages.github.com/">公式サイトの手順</a> に従って、自身のウェブサイトをデプロイするためのリポジトリを作成します。また本記事では、<strong>Hugo プロジェクトのリポジトリはデプロイ用リポジトリとは別で扱うため、Hugo プロジェクトのリポジトリも新たに作成します。</strong></p> <p>本記事では Hugo プロジェクトのリポジトリ名は <code>hugo-blog</code> という名前に設定した前提で進めていきます。また作成したリモートリポジトリの情報は、下記コマンドで Hugo プロジェクトに登録しておきます。</p> <pre><code class="bash"># Hugo プロジェクトフォルダのルートで Git リポジトリを作成する git init # Hugo プロジェクトのリポジトリ情報を登録しておく (hugo-blog の GitHub URL) git remote add origin <Hugo プロジェクトのリポジトリの URL> </code></pre> <h2 id="GitHub Actions で Hugo のビルドからデプロイまでを自動化するための環境を整える"><a href="#GitHub+Actions+%E3%81%A7+Hugo+%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E3%81%8B%E3%82%89%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%BE%E3%81%A7%E3%82%92%E8%87%AA%E5%8B%95%E5%8C%96%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E7%92%B0%E5%A2%83%E3%82%92%E6%95%B4%E3%81%88%E3%82%8B">GitHub Actions で Hugo のビルドからデプロイまでを自動化するための環境を整える</a></h2> <p>今回は <code>hugo-blog</code> という Hugo プロジェクトのリポジトリから、デプロイ用リポジトリへデプロイしたいため、まずはデプロイ用リポジトリでデプロイキーを登録します。<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/developers/overview/managing-deploy-keys#%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%82%AD%E3%83%BC">公式サイトの手順</a> に従いデプロイキーを登録したら、秘密鍵を <code>hugo-blog</code> リポジトリのシークレットに登録します。</p> <p>シークレットは <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/actions/reference/encrypted-secrets#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%95%E3%82%8C%E3%81%9F%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90">公式サイトの手順</a> に従って登録します。今回は秘密鍵をシークレットに登録する際の名前に <code>ACTIONS_DEPLOY_KEY</code> を設定した前提で進めていきます。</p> <p>次に <a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action">GitHub Pages action</a> を導入して Hugo のビルドから公開までを自動化する環境をセットアップします。</p> <p><code>hugo-blog</code> リポジトリに GitHub Pages action の <a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action#getting-started">Getting started</a> を参考にワークフローファイルを追加します。<code>- name: Deploy</code> の項目のみデプロイ用リポジトリへデプロイするために設定内容を変更します。</p> <pre><code class="yaml"># .github/workflows/gh-pages.yml name: github pages on: push: branches: - main # Set a branch name to trigger deployment jobs: deploy: runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 with: submodules: true # Fetch Hugo themes (true OR recursive) fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod - name: Setup Hugo uses: peaceiris/actions-hugo@v2 with: hugo-version: '0.78.2' - name: Build run: hugo --minify # - name: Deploy # uses: peaceiris/actions-gh-pages@v3 # with: # github_token: $<span>{</span><span>{</span> secrets.GITHUB_TOKEN <span>}</span><span>}</span> # publish_dir: ./public - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: deploy_key: $<span>{</span><span>{</span> secrets.ACTIONS_DEPLOY_KEY <span>}</span><span>}</span> external_repository: nikaera/nikaera.github.io publish_branch: main cname: nikaera.com </code></pre> <p><code>- name: Deploy</code> の項目で設定した各種パラメータは下記になります。</p> <div class="table-responsive"><table> <thead> <tr> <th>キー</th> <th>説明</th> </tr> </thead> <tbody> <tr> <td>deploy_key</td> <td>デプロイ時に使用する秘密鍵</td> </tr> <tr> <td>external_repository</td> <td>デプロイ先のリモートリポジトリ</td> </tr> <tr> <td>publish_branch</td> <td>デプロイ先のリモートリポジトリのブランチ</td> </tr> <tr> <td>cname</td> <td>設定するカスタムドメイン名</td> </tr> </tbody> </table></div> <p><code>deploy_key</code> にはシークレットに登録した秘密鍵を設定します。<code>external_repository</code> には Hugo をビルドした際のデプロイ先リポジトリを <code><ユーザ名>/<リポジトリ名></code> のフォーマットで指定します。<code>publish_branch</code> はデプロイ先として使用するブランチ名になります。<code>cname</code> には自分が設定したいドメイン名を指定します。<code>cname</code> の <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site">詳細</a> はこちらからご確認いただけます。</p> <h2 id="カスタムドメインで設定した内容で DNS 設定を書き換える"><a href="#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%A7%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E5%86%85%E5%AE%B9%E3%81%A7+DNS+%E8%A8%AD%E5%AE%9A%E3%82%92%E6%9B%B8%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%8B">カスタムドメインで設定した内容で DNS 設定を書き換える</a></h2> <p>GitHub Pages にカスタムドメインを利用する際は、該当するドメインの DNS レコードの設定で CNAME レコードもしくは A レコードを設定する必要があります。<a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site">公式サイトの手順</a> に従って設定します。</p> <p>また、カスタムドメインの設定後は特別な理由がない限りは、デプロイ用リポジトリで <a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/securing-your-github-pages-site-with-https">HTTPS 強制の設定</a> をしておくことオススメします。</p> <p>ちなみに GitHub Pages で利用している証明書は <a target="_blank" rel="nofollow noopener" href="https://github.blog/2018-05-01-github-pages-custom-domains-https/">Let's Encrypt</a> のものになります。</p> <p>設定作業はこれで完了です。あとは実際に Hugo プロジェクトを更新後、<code>hugo-blog</code> リポジトリに push することでビルドからデプロイまで GitHub Actions で行われるようになったかを確認していきます。</p> <h2 id="Hugo プロジェクトの更新時に自動でデプロイが行われるか確認する"><a href="#Hugo+%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E6%9B%B4%E6%96%B0%E6%99%82%E3%81%AB%E8%87%AA%E5%8B%95%E3%81%A7%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%8C%E8%A1%8C%E3%82%8F%E3%82%8C%E3%82%8B%E3%81%8B%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B">Hugo プロジェクトの更新時に自動でデプロイが行われるか確認する</a></h2> <p>Hugo プロジェクトには既に <code>hugo-blog</code> リポジトリの GitHub URL が <code>origin</code> として設定されているはずなので、下記で実際に <code>hugo-blog</code> リポジトリへ push してみます。</p> <pre><code class="bash"># Hugo プロジェクトを hugo-blog リポジトリに push する git add -A git commit -m "initial commit" git push origin main </code></pre> <p>次は実際に GitHub リポジトリの <code>Actions</code> タブから、GitHub Pages action のワークフローが実行されているか確認します。</p> <p><img src="https://i.gyazo.com/d4c3c5477c0f149ae84464fcc63c593b.png" alt="GitHub Pages actions の実行に成功した様子" /><br /> <strong>GitHub Pages actions の実行に成功した様子</strong></p> <p>無事ワークフローの実行に成功したことを確認したら、デプロイ用リポジトリの様子を確認します。</p> <p><img src="https://i.gyazo.com/3a0eb5ca58701a39bb922ea14477488c.png" alt="デプロイ用リポジトリに Hugo の最新ビルドが push されていることを確認する" /><br /> <strong>デプロイ用リポジトリに Hugo の最新ビルドが push されていることを確認する</strong></p> <p>最新コミットのメッセージに <code>deploy: <ユーザ名>/hugo-blog@<コミットハッシュ></code> のコメントが表示されているはずです。コメントのリンクをクリックすると、<code>hugo-blog</code> リポジトリの最新コミットの確認画面に遷移するはずです。</p> <p>ここまで確認できれば、あとはローカルで <code>hugo server</code> して確認していたウェブサイトと同じように、GitHub Pages 上でもウェブサイトが見えるか実際に確認してみます。</p> <p>デプロイ用リポジトリ名が <code><ユーザ名>/<ユーザ名>.github.io</code> であった場合、<code>https://<ユーザ名>.github.io</code> でウェブサイトにアクセスできます。私の場合は <code>https://nikaera.github.io</code> になります。その際、カスタムドメインにリダイレクトすることも確認できれば、カスタムドメインの設定も正常に反映されています。</p> <p><img src="https://i.gyazo.com/b3c061569dae33a1dd58f4741c6d77cc.png" alt="ページが正常に表示できカスタムドメインでもアクセスできている様子" /><br /> <strong>ページが正常に表示されていてカスタムドメインでアクセスできた様子</strong></p> <p>アクセス時に意図したページが表示されていることが確認できれば大丈夫です。これで自分のウェブサイトを更新したら <code>hugo-blog</code> リポジトリに Hugo プロジェクトを push するだけで自分のウェブサイトを自動更新できるようになりました。</p> <h1 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h1> <p>今回は Hugo を例にしましたが、本記事内で紹介した <a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action">GitHub Pages action</a> は <a target="_blank" rel="nofollow noopener" href="https://jamstack.org/generators/">様々な SSG</a> に対応しています。そのため Hugo ではウェブサイトのカスタマイズに限界が来たなと感じたら <a target="_blank" rel="nofollow noopener" href="https://nextjs.org/">Next.js</a> や <a target="_blank" rel="nofollow noopener" href="https://www.gatsbyjs.com/">Gatsby</a> に乗り換えるといったことも可能です。</p> <p>また Hugo では何も考えずとも、マークダウンで記事が書けてビルドも高速なので、手っ取り早く自分のウェブサイトを構築してみたいという用途にはピッタリだと感じました。</p> <p>関係ないですが、Hugo でウェブサイト構築する際の知見も記事に含めてしまったせいで、文章量が意図した倍近い量になってしまいました。。簡潔で分かりやすい文章が書けるようにならなきゃ。。</p> <h1 id="参考リンク"><a href="#%E5%8F%82%E8%80%83%E3%83%AA%E3%83%B3%E3%82%AF">参考リンク</a></h1> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/">The world’s fastest framework for building websites | Hugo</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://themes.gohugo.io/">Complete List | Hugo Themes</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/about-github-pages">GitHub Pages について - GitHub Docs</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/marketplace/actions/github-pages-action">GitHub Pages action</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/getting-started/installing/">Install Hugo | Hugo</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/getting-started/quick-start/#step-3-add-a-theme">Quick Start | Hugo</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://gohugo.io/hosting-and-deployment/hosting-on-github/">Host on GitHub | Hugo</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://pages.github.com/">GitHub Pages | Websites for you and your projects, hosted directly from your GitHub repository. Just edit, push, and your changes are live.</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/developers/overview/managing-deploy-keys#%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%82%AD%E3%83%BC">デプロイキーの管理 - GitHub Docs</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/actions/reference/encrypted-secrets#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%95%E3%82%8C%E3%81%9F%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90">暗号化されたシークレット - GitHub Docs</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site">GitHub Pages サイトのカスタムドメインを管理する - GitHub Docs</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://docs.github.com/ja/free-pro-team@latest/github/working-with-github-pages/securing-your-github-pages-site-with-https">HTTPS で GitHub Pages サイトを保護する - GitHub Docs</a></li> </ul> nikaera tag:crieit.net,2005:PublicArticle/15810 2020-04-04T10:47:33+09:00 2020-04-04T15:57:22+09:00 https://crieit.net/posts/github-actions-build-lastmod hugoをgithub-actions上でbuildした際、lastmodの更新がすべての記事に適用される問題を解決した <h2 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://tech-wafter.net/2020/build-hugo-homepage-by-github-action/">hugoのジェネレートをGitHub-actionsを使って、pushするだけでデプロイできるようにした</a>のですが、全記事の最終更新日が更新されていたため原因調査をおこないました。</p> <h2 id="TL;DR"><a href="#TL%3BDR">TL;DR</a></h2> <ul> <li>gitのcloneを行う際に最新コミットしか取得していなかった</li> <li><code>actions/checkout</code>を利用する場合は以下の方法でfetchを行わせ、全履歴を取得しておく</li> </ul> <pre><code class="yaml">- uses: actions/checkout@v2 with: fetch-depth: 0 # Fetch all history for .GitInfo and . </code></pre> <h2 id="試したこと"><a href="#%E8%A9%A6%E3%81%97%E3%81%9F%E3%81%93%E3%81%A8">試したこと</a></h2> <h3 id="GitHub-actions上とlocalの比較"><a href="#GitHub-actions%E4%B8%8A%E3%81%A8local%E3%81%AE%E6%AF%94%E8%BC%83">GitHub-actions上とlocalの比較</a></h3> <div class="table-responsive"><table> <thead> <tr> <th align="center">icon</th> <th align="center">結果</th> </tr> </thead> <tbody> <tr> <td align="center">✅</td> <td align="center">更新対象記事のみlastmodが更新されていた</td> </tr> <tr> <td align="center">❎</td> <td align="center">すべての記事に対して更新が入っていた</td> </tr> </tbody> </table></div> <ul> <li>ローカル <ul> <li>✅MacOSでのビルド</li> <li>✅Vagrant内のUbuntu:18.04.4でのビルド</li> </ul></li> <li><p>CI環境</p> <ul> <li>❎Ubuntu:ubuntu-18.04でのビルド</li> <li>❎MacOS:latestでのビルド</li> <li>✅hugoのビルドを省いてデプロイ</li> <li>❎オプションを外してビルド</li> <li><p>❎既存のworkflowを使わずにコマンドでインストール(下記コマンドを実行)</p> <pre><code class="bash">wget https://github.com/gohugoio/hugo/releases/download/v0.68.3/hugo_0.68.3_Linux-64bit.deb sudo apt-get install -y ./hugo_0.68.3_Linux-64bit.deb </code></pre></li> </ul></li> </ul> <h3 id="git周りの確認"><a href="#git%E5%91%A8%E3%82%8A%E3%81%AE%E7%A2%BA%E8%AA%8D">git周りの確認</a></h3> <ul> <li>参照先のcommitIDが対象コミットのcommitIDになっているか <ul> <li>対象のコミットIDでした</li> </ul></li> <li><code>git log</code>の結果が正常に表示されているか <ul> <li><strong>CI上のログでは、1件しか表示されていなかった</strong></li> </ul></li> </ul> <h2 id="結果"><a href="#%E7%B5%90%E6%9E%9C">結果</a></h2> <p><code>actions/checkout@v2</code>という公式のworkflowを利用してgitのcloneを行っていたのですが、デフォルトでは最新のコミットしか取ってこないようです。<br /> 更新日時の参照先が見つけられなくなるため、すべての記事が最新のコミット更新日時を取得しに行ってしまったのだと思います。</p> <blockquote> <pre><code class="markdown"># Number of commits to fetch. 0 indicates all history. # Default: 1 fetch-depth: '' </code></pre> <p>https://github.com/actions/checkout#usage</p> </blockquote> <p>すべての履歴をcloneしてくることで、解決しました。<br /> GitHub Actionsのymlファイルでは、以下のように記載するようです。</p> <blockquote> <pre><code class="yaml">- uses: actions/checkout@v2 with: fetch-depth: 0 # Fetch all history for .GitInfo and . </code></pre> <p>https://github.com/peaceiris/actions-hugo#️-create-your-workflow</p> </blockquote> <h2 id="さいごに"><a href="#%E3%81%95%E3%81%84%E3%81%94%E3%81%AB">さいごに</a></h2> <p>最初はhugoのセットアップに使っているworkflowが悪いのかを疑ってたせいで、結構解決までに時間がかかりました…</p> <p>今回のような問題を早期発見するために、確認用のStepも入れたほうが良いのかなと思いました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/actions/checkout">actions/checkout: Action for checking out a repo</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/peaceiris/actions-hugo">peaceiris/actions-hugo: GitHub Actions for Hugo ⚡️ Setup Hugo quickly and build your site fast. Hugo extended, Hugo Modules, Linux (Ubuntu), macOS, and Windows are supported.</a></li> </ul> matsu4ki tag:crieit.net,2005:PublicArticle/14608 2018-11-20T18:04:59+09:00 2018-12-20T15:15:12+09:00 https://crieit.net/posts/Hugo Hugoでブログ付きのポートフォリオサイト <p>この記事はCrieitの「<a href="https://crieit.net/advent-calendars/2018/crieit">アドベントカレンダー Advent Calendar 2018</a>」の11日目の記事です。<br /> 昨日は<a href="https://crieit.net/users/Naturalclar">Naturalclar</a>さんの<a href="https://crieit.net/posts/Twitter">米国からTwitter転職で日本に来たら楽しくて仕方ない話</a>でした!</p> <h1 id="背景"><a href="#%E8%83%8C%E6%99%AF">背景</a></h1> <p><del>アドベントカレンダーのネタのために何か作らなくちゃ</del>静的なサイトでお手軽なサイトでも立ち上げようかと思いGolangの勉強がてらHugoでサイトを構築してみました。</p> <h1 id="苦肉の策"><a href="#%E8%8B%A6%E8%82%89%E3%81%AE%E7%AD%96">苦肉の策</a></h1> <p>とにかく時間がないので、ちゃっちゃと終わらせるために、Hugoはhomebrewでインストールして、一度構築用のリポジトリを作成しておき、Github Pagesならぬ、Bitbucket Pages(そんなサービスは無い)にあげてGoogle Analyticsで監視するようにしました。</p> <p>※Bitbucket Cloudというみたいです。</p> <p><a target="_blank" rel="nofollow noopener" href="https://confluence.atlassian.com/bitbucket/publishing-a-website-on-bitbucket-cloud-221449776.html">https://confluence.atlassian.com/bitbucket/publishing-a-website-on-bitbucket-cloud-221449776.html</a></p> <h1 id="実際のサイト"><a href="#%E5%AE%9F%E9%9A%9B%E3%81%AE%E3%82%B5%E3%82%A4%E3%83%88">実際のサイト</a></h1> <p><a target="_blank" rel="nofollow noopener" href="https://hugofkworld.bitbucket.io/">https://hugofkworld.bitbucket.io/</a></p> <p><a href="https://crieit.now.sh/upload_images/90e98713db199120d58ae0345db13ecf5bf3cd1164b1f.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/90e98713db199120d58ae0345db13ecf5bf3cd1164b1f.png?mw=700" alt="https://hugofkworld.bitbucket.io/" /></a></p> <p>構築用のソースコードは<a target="_blank" rel="nofollow noopener" href="https://[email protected]/hugofkworld/hugo-fk-world.git">こちら</a><br /> 運用用のソースコードは<a target="_blank" rel="nofollow noopener" href="https://[email protected]/hugofkworld/hugofkworld.bitbucket.io.git">こちら</a></p> <p>多言語対応できるテンプレートを使ったのですが、JPサイトが空だったり、Projectsが空だったりしますが、ちびちび書き足していきます。</p> <p>blogもこちらがキャッチーなのでうまく運用維持できたら更新していくかもしれません。</p> <h1 id="参考にしたサイト"><a href="#%E5%8F%82%E8%80%83%E3%81%AB%E3%81%97%E3%81%9F%E3%82%B5%E3%82%A4%E3%83%88">参考にしたサイト</a></h1> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/syui/items/869538099551f24acbbf">Bitbucketで静的ウェブサイトを公開する</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/syui/items/869538099551f24acbbf">HUGOを使ってサイトを立ち上げる方法</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://dev.to/dgavlock/creating-a-hugo-site-on-github-pages-3cjo">Creating a Hugo site on GitHub Pages </a></li> </ul> <p>明日は<a href="https://crieit.net/users/rubys8arks">かしい@お笑いSNS作成中</a>さんの記事です!</p> fk2000