こんにちは。
今回は、前回の記事で書いた通り、ContentfulとmicroCMSをRailsに組み込んだ時の比較をしてみたいと思います。
結論、microCMSの方が個人的には扱いやすいかな?と思いましたので、その理由を3つに分けてお伝えしていきます。
また、microCMSについては前回の記事で詳しく書いているので、そちらも合わせてご覧ください。
1. Contentfulの値の取得は独自のIDを使ってしまう
Contentfulには、contentful.rb
というgemがあります。
gemがあるのでこっちの方が便利そうじゃん!と思って使ってみたのですが、独特な書き方になります。
例えば、以下のような形でデータを取得できます。
gem 'contentful'
class ArticlesController < ApplicationController
def index
@articles = ContentfulClient.new.fetch_entries
end
def show
@article = ContentfulClient.new.fetch_entry_by_slug(slug: params[:slug])
end
end
class ContentfulClient
DEFAULT_CONTENT_TYPE = 'articles'.freeze
DEFAULT_SELECTS = %w[
fields.title
fields.slug
fields.headerImage
fields.createdAt
].freeze
ALL_SELECTS = %w[
fields.title
fields.slug
fields.headerImage
fields.createdAt
fields.body
].freeze
def initialize
@client = Contentful::Client.new(
space: Rails.application.credentials.dig(:contentful, :space),
access_token: Rails.application.credentials.dig(:contentful, :access_token),
)
end
def fetch_entries(content_type: DEFAULT_CONTENT_TYPE, select: DEFAULT_SELECTS)
@client.entries(content_type: content_type, select: select)
end
def fetch_entry_by_slug(content_type: DEFAULT_CONTENT_TYPE, slug:, select: ALL_SELECTS)
@client.entries(content_type: content_type, 'fields.slug' => slug, select: select).first
end
def fetch_asset_by_id(id:)
@client.asset(id)
end
end
特に#fetch_entry_by_slug
をみてもらうとわかるのですが、記事の一覧を取得した後にslugを指定して記事を取得するという形になっています。
最後に.first
としていることから、イメージが伝わりやすいかなと思います
そもそも記事は固有のIDを持っていて、それがランダムで割り振られる値になってしまうため、例えば/articles/compare-microcms-and-contentful
というURLにしたいときはslug
というフィールドを作って、そこにcompare-microcms-and-contentful
という値を入れておき、それを使って記事を取得するという形になります。
詳しく内部の処理まで追っているわけではないのですが、記事のうち特定の記事を探してくる時に一旦全部の記事を取得してから、その中から探してくるという形になっていそうなところもイマイチだなというふうに感じてしまいました。
microCMSでは、そもそもIDを変更することができるので、/articles/compare-microcms-and-contentful
というURLにしたいときは、IDをcompare-microcms-and-contentful
という値にしておけば、そのままURLに使うことができるという点が便利だなと感じました。
(microCMSの方は前回の記事に書いているので割愛します)
2. Contentfulの返り値は独自のHashになっている
上記のように記事を取得した次に、記事の中身を表示するときには、rich textのような複雑なデータが入っているので、それを表示するためには、パースをする必要があります。
Contentfulでは、そのパースをするためのgemが用意されているのですが、それがそのまま使用すると画像を埋め込んだ時などにエラーになってしまうので、パーサーをカスタマイズする必要があります。
gem 'rich_text_renderer'
= @article.title
%div.w-full
= render RichText::Component.new(richtext: @article.body)
class RichText::Component < ViewComponent::Base
def initialize(richtext:)
@richtext = richtext
@renderer = RichTextRenderer::Renderer.new(
'embedded-asset-block' => EmbedAssetRenderer,
'embedded-entry-block' => EmbedEntryRenderer
)
end
end
class EmbedAssetRenderer < RichTextRenderer::BaseNodeRenderer
def render(node)
id = node['data']['target']['sys']['id']
"<img src=#{src(id: id)} />"
end
def src(id:)
"https:#{ContentfulClient.new.fetch_asset_by_id(id: id).url}"
end
end
class EmbedEntryRenderer < RichTextRenderer::BaseNodeRenderer
def render(node)
# 途中で諦めたので割愛しますw
end
end
こんな感じで、例えば記事内に別の記事を埋め込みたいときや、画像を埋め込みたいときには、embedded-asset-block
というタイプのノードをパースするためのクラスを作成する必要があります。
この辺りも細かくこだわりたいケースでは有効なのですが、今回は記事はあくまで全体の1コンテンツであるため、そこまで便利だなと感じられるものではありませんでした。
microCMSでは、記事の中身はMarkdownでそのまま返ってくるので、よくあるMarkdownのパーサーを使えばそのまま表示することができそうです。
ただ、例えば別の記事を埋め込む時に特別な表示にしたいなどの場合は、前述の理由からContentfulの方が便利そうです。
3. microCMSの方がドキュメントが読みやすい
microCMSの方は、ドキュメントが非常に読みやすいです。
Contentfulの方は、ドキュメントがそもそも不十分だったり、前述したgemの使い方はGitHubのREADMEに書かれていることが多いのでなかなか探すのに苦労しました。
これは僕が日本人だから、というのも大きいかもしれませんが…
まとめ
今回は、microCMSとContentfulの比較をしてみました。
最初に書いた通り、microCMSの方が便利だなと感じています。
現状だとどちらを使用するケースでも無料枠の範囲内で使えそうですが、もし有料になった時もmicroCMSの方が安いので、そこも意思決定に大きく影響すると思います。
今回はこのあたりで。