Hugoの速度、セキュリティ、シンプルさが目を引きましたが、この静的サイトジェネレーターは、あなたとあなたの非技術チームの両方を満足させることができますか?
記事上で、 ヘッドレスCMSからHugoサイトのデータをフィードする方法を紹介します。これにより、開発者は静的サイトのメリットを享受しながら、コンテンツ作成者が好きなツールを使用できるようになります。
「 燃え尽き症候群に反応する」こと がどのように私をヒューゴに導いたか 静的サイトジェネレーター(SSG)は最近勢いを増しており、テクノロジーニュースフィードの概念に数週間衝撃を受けた後、傾向をよりよく理解する必要があると感じました。調査の結果、多くの著名なSSGがReactを使用していることがわかったので、JavaScriptのスキルを向上させ始めました。私はいくつかのきちんとしたReactプロトタイプを作成しましたが、エラーが発生したり、コードで迷子になったりしました。問題がJavaScript、React、JSXのいずれにあるのかを解明するのに苦労しました。それは、非常に苛立たしいことでした。たくさんのことを学びましたが、それは謙虚な経験でした。
私は燃え尽き症候群を避けるために他のオプションを検討し始めました。 State of Jamstack 2020 Report でのHugoの人気が私の興味をそそったので、いくつかのチュートリアルを見ました。簡単そうだったので、「クイックスタート」チュートリアルを起動して実験しました。 2週間以内に、 Hugoの経験 がゼロから、選択したヘッドレスCMSからコンテンツを取得する作業サイトに移行しました。 Reactとの最初の出会いと比べてなんと違います!
Hugoとは何ですか? Hugoは、ファイルとテンプレートのソースディレクトリを取得し、これらを入力として使用して完全なWebサイトを作成します。GO上に構築され、独自のテンプレート言語を備えており、どこでもホストできます。 Hugoチームは(大胆に)それがウェブサイトを構築するための世界最速のフレームワークであり、最も人気のあるオープンソースの静的サイトジェネレーターの1つであり、スポーツであると主張しています 驚くべきスピードと柔軟性。
それはあなたにとってどういう意味ですか? 高度なReactの概念や複雑なJSを習得しなくても、静的に生成されたサイトのメリットを享受できます。 GOでプログラミングする方法を本当に知る必要はありません。いくつかの基本的なHugoテンプレートの概念、HTML / CSS、およびHugoのディレクトリ規則に関する知識を身に付ければ、サイトを構築するのに十分です。
私の経験では、高速でシンプルですが、2つの欠点が見つかりました。
箱から出して動的ページを真に作成する機能 はありません。ルーティングの処理など、Hugoのすぐに使用できる機能を使用するには、コンテンツが「content」ディレクトリに物理的に存在する必要があります。つまり、デフォルトでは、外部システム(CMSなど)で作成されたページをプロジェクトに動的に追加することはできません。 Hugoは、限られたコンテンツ作成ツールで物理的なマークダウンファイルを使用します。 これらの制限は、技術以外のチームにとってどのような意味がありますか? 誰もがMarkdownを好きというわけではありません。ほとんどのコンテンツクリエーターは、端末のようなエディターに# または* 記号を打ち込むよりもグラフィックなエクスペリエンスを望んでいると思います。また、ワークフローや共同編集などに慣れてきた貴重なCMS機能も見逃しています。何よりも悪いことに、Hugoでは、コードファイルと一緒に存在する マークダウンファイルに直接変更を加える必要があります(😱)。
では、チームのコンテンツ作成のニーズとHugoを使用したいという願望の間のギャップをどのように埋めることができますか?
恐れることはありません、CMSはここにあります! 開発者とコンテンツ作成者の両方をHugoに満足 させるための重要な要素は、ヘッドレスCMSを統合することです。 ヘッドレスCMSは、編集カレンダー などのコンテンツ作成ツールを提供します。
編集カレンダー 同時編集 などのコラボレーション機能:
このような生活の質の高い機能は、コンテンツの作成者や編集者を満足させます。開発者としてのあなたはどうですか?さて、あなたはそれのクラウドベースとして、ホストにそれを持っていない、と あなたは、単純なデータ収集のためのSDKを取得します。それは素晴らしいと思いませんか?
私のソリューションを5つのステップで要約します。
Hugoのセットアップ HugoをヘッドレスCMSに接続する JSONをMarkdownに変換する ビルドスクリプトの使用 サイトの展開 Hugoのセットアップ まず、Hugo をインストールする必要がありました。 Hugoは複数のプラットフォームで実行できます。私はWindowsマシンを使用しているため、ドキュメントに従ってChocolateyを使用しました。
choco install hugo -confirm
Hugoをインストールしたら、新しいサイトコマンドを実行しました。
hugo new site kontent-hugo-articles
これにより、すぐに開始するために必要なすべての定型ディレクトリを備えた新しいHugoサイトが作成されました。次のコマンドを使用して、新しいマークダウンファイルを作成しました。
cd quickstart
そして、新しく作成したファイルにマークダウンコンテンツを追加しました。
--- title: 'How to Make the Team Happy with Hugo and Headless' draft: false The speed, security, and simplicity of Hugo caught your eye, but can this static site generator satisfy both you and your non-technical team? In this article, I'll show you how to feed a Hugo site data from a headless CMS, so developers can reap the benefits of a static site while allowing content creators to use the tools they love.
--- title: 'How to Make the Team Happy with Hugo and Headless' draft: false The speed, security, and simplicity of Hugo caught your eye, but can this static site generator satisfy both you and your non-technical team? In this article, I'll show you how to feed a Hugo site data from a headless CMS, so developers can reap the benefits of a static site while allowing content creators to use the tools they love.
--- title: 'How to Make the Team Happy with Hugo and Headless' draft: false The speed, security, and simplicity of Hugo caught your eye, but can this static site generator satisfy both you and your non-technical team? In this article, I'll show you how to feed a Hugo site data from a headless CMS, so developers can reap the benefits of a static site while allowing content creators to use the tools they love.
--- title: 'How to Make the Team Happy with Hugo and Headless' draft: false The speed, security, and simplicity of Hugo caught your eye, but can this static site generator satisfy both you and your non-technical team? In this article, I'll show you how to feed a Hugo site data from a headless CMS, so developers can reap the benefits of a static site while allowing content creators to use the tools they love.
テストコンテンツが作成され、構造が確立されたら、レイアウト ディレクトリに_default サブディレクトリを追加し、single.html およびlist.html レイアウトを作成しました。
〜/ layout / _default / list.html:
〜/ layout / _default / single.html:
{{ .Content }}
コマンドhugoserverを 実行すると、サンプルコンテンツをテストするサーバーが起動しました。
基本が稼働しているので、ヘッドレスCMSの統合を開始できました。
HugoをヘッドレスCMSに接続する すばやく立ち上げて実行するために、 Kentico Kontentのサンプルプロジェクト を使用することを選択し、そこに含まれる既成の記事を取得することに重点を置きました。
Hugoはデフォルトでマークダウン形式を使用するため、コンテンツをフェッチしてマークダウンファイルに変換する必要がありました。これを実現するために、最初にNode.js をインストールし、npmを使用してコンテンツを取得するためのKentico Kontent Delivery JavaScriptSDKをインストールしました。
npm i rxjs --save npm i @kentico/kontent-delivery --save
ライブラリがインストールされたら、プロジェクトにcms-scripts ディレクトリを作成して、CMS実装の詳細をHugoのものから分離しました。
ここからは、 Kontent Delivery SDKのドキュメント に従って、Delivery Clientをセットアップし、APIを介してKontentプロジェクトの記事を取得する必要がありました。このロジックを2つのファイルに分けました。 cms-scripts / config.js:
const KenticoContent = require ( '@kentico/kontent-delivery' ); const deliveryClient = new KenticoContent.DeliveryClient({ projectId : ' '
}); exports .deliveryClient = deliveryClient;
const KenticoContent = require ( '@kentico/kontent-delivery' ); const deliveryClient = new KenticoContent.DeliveryClient({ projectId : ' '
}); exports .deliveryClient = deliveryClient;
cms-scripts / buildArticles.js:
const { deliveryClient } = require ( './config' ) const subscription = deliveryClient.items() .type( 'article' ) .depthParameter( 2 ) .toObservable() .subscribe( response => { console .log(response) })
node cms-scripts/buildArticles.js
すると、KontentDeliveryエンドポイントからJSON応答が発生しました。さて、応答をHugoが期待する物理的なマークダウンファイルに変換する時が来ました。
JSONをMarkdownに変換する KontentのJSONをHugoのデフォルトのマークダウンファイル形式に変換するには、次の3つのレイヤーがあります。
応答からのコンテンツの抽出:
cms-scripts / buildArticles.js:
//code continued from cms-scripts/buildArticles.js
//...
const markdownConverter = require ( './markdownConverter' ); //...
.subscribe( response => { for ( var item of response.items){ //frontmatter:
const title = item.title.value const codename = item.system.codename //correct mismatch between Kontent date format and Hugo's expected format
let date = new Date ( Date .parse(item.post_date.value)) date = date.toISOString() //article content
const body_copy = item.body_copy.resolveHtml() const teaser_image = item.teaser_image.value[ 0 ] //convert JSON values to markdown
const data = markdownConverter.convert(title, date, body_copy, teaser_image) } });
//code continued from cms-scripts/buildArticles.js
//...
const markdownConverter = require ( './markdownConverter' ); //...
.subscribe( response => { for ( var item of response.items){ //frontmatter:
const title = item.title.value const codename = item.system.codename //correct mismatch between Kontent date format and Hugo's expected format
let date = new Date ( Date .parse(item.post_date.value)) date = date.toISOString() //article content
const body_copy = item.body_copy.resolveHtml() const teaser_image = item.teaser_image.value[ 0 ] //convert JSON values to markdown
const data = markdownConverter.convert(title, date, body_copy, teaser_image) } });
//code continued from cms-scripts/buildArticles.js
//...
const markdownConverter = require ( './markdownConverter' ); //...
.subscribe( response => { for ( var item of response.items){ //frontmatter:
const title = item.title.value const codename = item.system.codename //correct mismatch between Kontent date format and Hugo's expected format
let date = new Date ( Date .parse(item.post_date.value)) date = date.toISOString() //article content
const body_copy = item.body_copy.resolveHtml() const teaser_image = item.teaser_image.value[ 0 ] //convert JSON values to markdown
const data = markdownConverter.convert(title, date, body_copy, teaser_image) } });
Turndown.js ( npm install turndown
)を使用して抽出されたJSONコンテンツをマークダウンに変更するマークダウンコンバーター を作成します。
cms-scripts / markdownConverter.js:
const TurndownService = require ( 'turndown' ); const convert = ( title, date, body_copy, teaser_image ) => { //markdown conversion
const turndownService = new TurndownService() const markdown = turndownService.turndown(body_copy) const header_image = turndownService.turndown( ` ${teaser_image.url} ' alt=' ${teaser_image.description} '/>` ) const data = `--- title: ' ${title} ' date: ${date}
draft: false --- ${header_image}
${markdown}
`
return data exports .convert = convert;
const TurndownService = require ( 'turndown' ); const convert = ( title, date, body_copy, teaser_image ) => { //markdown conversion
const turndownService = new TurndownService() const markdown = turndownService.turndown(body_copy) const header_image = turndownService.turndown( ` ${teaser_image.url} ' alt=' ${teaser_image.description} '/>` ) const data = `--- title: ' ${title} ' date: ${date}
draft: false --- ${header_image}
${markdown}
`
return data exports .convert = convert;
Nodeの組み込みfs ライブラリを使用して、Hugoコンテンツディレクトリまたはサブフォルダに物理ファイルを作成します。
cms-scripts / buildArticles.js(完全なコード):
const { deliveryClient } = require ( './config' ) const markdownConverter = require ( './markdownConverter' ); const fs = require ( 'fs' ); const subscription = deliveryClient.items() .type( 'article' ) .depthParameter( 2 ) .toObservable() .subscribe( response => { for ( var item of response.items){ //frontmatter:
const title = item.title.value const codename = item.system.codename //correct mismatch between Kontent date format and Hugo's expected format
let date = new Date ( Date .parse(item.post_date.value)) date = date.toISOString() //article content
const body_copy = item.body_copy.resolveHtml() const teaser_image = item.teaser_image.value[ 0 ] //convert JSON values to markdown
const data = markdownConverter.convert(title, date, body_copy, teaser_image) fs.writeFileSync( `content/articles/ ${codename} .md` , data) } });
const { deliveryClient } = require ( './config' ) const markdownConverter = require ( './markdownConverter' ); const fs = require ( 'fs' ); const subscription = deliveryClient.items() .type( 'article' ) .depthParameter( 2 ) .toObservable() .subscribe( response => { for ( var item of response.items){ //frontmatter:
const title = item.title.value const codename = item.system.codename //correct mismatch between Kontent date format and Hugo's expected format
let date = new Date ( Date .parse(item.post_date.value)) date = date.toISOString() //article content
const body_copy = item.body_copy.resolveHtml() const teaser_image = item.teaser_image.value[ 0 ] //convert JSON values to markdown
const data = markdownConverter.convert(title, date, body_copy, teaser_image) fs.writeFileSync( `content/articles/ ${codename} .md` , data) } });
const { deliveryClient } = require ( './config' ) const markdownConverter = require ( './markdownConverter' ); const fs = require ( 'fs' ); const subscription = deliveryClient.items() .type( 'article' ) .depthParameter( 2 ) .toObservable() .subscribe( response => { for ( var item of response.items){ //frontmatter:
const title = item.title.value const codename = item.system.codename //correct mismatch between Kontent date format and Hugo's expected format
let date = new Date ( Date .parse(item.post_date.value)) date = date.toISOString() //article content
const body_copy = item.body_copy.resolveHtml() const teaser_image = item.teaser_image.value[ 0 ] //convert JSON values to markdown
const data = markdownConverter.convert(title, date, body_copy, teaser_image) fs.writeFileSync( `content/articles/ ${codename} .md` , data) } });
上記のスクリプトが配置されたら( このGitHubリポジトリ で確認できます)、ターミナルでnode cms-scripts/buildArticles.js
を再度実行することで、Hugoプロジェクトにコンテンツを追加し始めることができました。
/ content / articles ディレクトリにあるマークダウンファイルを使用しhugo server
実行してサイトをオンラインにすることができます。
私はショックを受けました!ヘッドレスCMSをわずか3つの小さなJavaScriptファイルでHugoに接続すると、間違いなく私の顔に笑顔がもたらされました。
ビルドスクリプトの使用 この時点で、ヘッドレスCMSコンテンツを使用するローカルで実行されているHugoサイトがありました。すごい! node cms-scripts/buildArticles.js
を手動で実行してプロジェクトにデータを入力し、続いて別のコマンドを実行してHugoサーバーを実行することは理想的ではありませんでした。このプロセスを合理化するために、 npm-run-all を使用しました。これにより、 package.json local:start
コマンドを使用して、Windowsマシンでスクリプトを一緒に実行できました。 〜/ package.json:
'scripts': { 'cms:prepare': 'node cms-scripts/buildArticles.js', 'local:start': 'npm-run-all -p cms:prepare local:serve',
'scripts': { 'cms:prepare': 'node cms-scripts/buildArticles.js', 'local:start': 'npm-run-all -p cms:prepare local:serve',
これにより、ローカルビルドが簡素化されるだけでなく、ホスト環境でビルドを自動化するための基礎が整います。
サイトの展開 私のHugoプロジェクトに完全に満足する前の最後の障害は次のとおりです。
全世界が見ることができるようにサイトを展開する ビルドプロセスの自動化 幸いなことに、どちらもNetlifyの ようなホスティングサービスで可能になります。 NetlifyへのデプロイはGitHubリポジトリに接続 するのと同じくらい簡単であるだけでなく、GitをプッシュするたびにWebサイトの自動ビルド を実行することもできます。
Netlifyをホスティングと自動ビルドに活用するために、 package.json を変更してNetlifyビルドスクリプトを含めました。
〜/ package.json:
'scripts': { 'cms:prepare': 'node cms-scripts/buildArticles.js', 'local:start': 'npm-run-all -p cms:prepare local:serve', 'netlify:serve': 'hugo -b $DEPLOY_PRIME_URL', },
'scripts': { 'cms:prepare': 'node cms-scripts/buildArticles.js', 'local:start': 'npm-run-all -p cms:prepare local:serve', 'netlify:serve': 'hugo -b $DEPLOY_PRIME_URL', },
'scripts': { 'cms:prepare': 'node cms-scripts/buildArticles.js', 'local:start': 'npm-run-all -p cms:prepare local:serve', 'netlify:serve': 'hugo -b $DEPLOY_PRIME_URL', },
'scripts': { 'cms:prepare': 'node cms-scripts/buildArticles.js', 'local:start': 'npm-run-all -p cms:prepare local:serve', 'netlify:serve': 'hugo -b $DEPLOY_PRIME_URL', },
これにより、Netlifyで「ビルドとデプロイビルドコマンド 」を設定できるようになりました。 Gitから新しいサイトを作成し、buildコマンドをnpm run netlify:build
publish
、PublishをPublishディレクトリ としてターゲットに設定しました。これらはすべてNetlifyインターフェイス内から行われます。これで、このプロジェクトのGitHubリポジトリでコードを変更すると、サイトが自動的に再構築されました。
この自動化をCMSのコンテンツ更新に拡張するために、Kontentのドキュメント に従ってKenticoKontentのWebhookとペアになっているNetlifyのビルドフックを使用しました。この追加により、コンテンツがKentico Kontentプロジェクトで公開または非公開になるたびに、Netlifyはサイトを再構築して、コンテンツが常に最新の状態になるようにします。
概要 この記事では、Hugoを紹介し、HugoをヘッドレスCMSに接続する方法と、それが開発者とコンテンツ作成者の両方にどのように役立つかについて説明しました。あなたとあなたの非技術的なチームメイトの両方が将来のプロジェクトでHugoと一緒に働くことを楽しむことができることをあなたに示したことを願っています!
この記事でHugoとKenticoKontentの可能性に興奮した場合は、より堅牢なHugo + Kontentサンプルサイトをここで 確認できます。