[Rails5]Heroku環境でsitemap.xmlを設置する方法

Rails

さくっとできるかなと思っていたが、Herokuは基本的にストレージへの書き込みができないため、全然さくっとできなかったので、その方法をまとめておく。

やりたいこと

Herokuで運用中のWebサービスにsitemap.xmlを設置したい。

結論

fog-awsを使って、sitemap.xmlをS3にアップロードする

Herokuはtmp以外にファイルの書き込みができないので、外部にsitemap.xmlを置くしかない。tmpは一定時間で削除されるので、今回のケースには利用できない。

環境情報

すでにCarrierwaveとfog-awsを利用してS3にアップロードしている。

Rails 5.2.2
carrierwave 1.3.1
mini_magick 4.9.2
fog-aws 3.3.0

対応方法

sitemap_generatorというGemを追加する。公式リポジトリの手順を参考に進める。

gem 'sitemap_generator'

gemをインストール

$ bundle install

Herokuのようなシステムの場合の対応方法がリポジトリのWikiにあるので、そちらを参考に進めていく。

Using Fog と Using CarrierWave が存在しているが、すでにfog-awsを利用している場合、Using CarrierWaveの方法だと上手くいかないので、Using Fogを利用する

config/sitemap.rb を下記のように記述。一部、例の通りだが、だいたいそのまま。今回のアプリでは、ENVでAWSの鍵やバケット名などを管理している。

SitemapGenerator::Sitemap.default_host = "https://example.com"
SitemapGenerator::Sitemap.sitemaps_host = "https://s3-ap-northeast-1.amazonaws.com/#{ENV['AWS_S3_BUCKET']}/"
SitemapGenerator::Sitemap.public_path = 'tmp/'
SitemapGenerator::Sitemap.sitemaps_path = 'sitemaps/'
SitemapGenerator::Sitemap.adapter = SitemapGenerator::S3Adapter.new(fog_provider: 'AWS',
                                         aws_access_key_id: ENV['AWS_ACCESS_KEY'],
                                         aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
                                         fog_directory: ENV['AWS_S3_BUCKET'],
                                         fog_region: 'ap-northeast-1')

sitemapの実際の中身は、config/sitemap.rbの下部に下記のように記述する。例) /articles/:id などを記述

SitemapGenerator::Sitemap.create do
  add root_path, changefreq: 'daily'
  add '/category1'
  add '/category2'
  Article.published.find_each do |article|
    add article_path(article), priority: 0.8, lastmod: article.updated_at
  end
end

クローラーにsitemapの場所を知らせる

public/robots.txt にsitemap.xmlの場所を記述する。ENVはrobots.txtで使えないはずなので、バケット名は直接書く。

Sitemap: https://s3-ap-northeast-1.amazonaws.com/[S3のバケット名]/sitemaps/sitemap.xml.gz

sitemapを定期的に作成する

rails sitemap:refresh(sitemap.xml.gzを作成し、検索エンジンに通知するコマンド)をHerokuのスケジューラに登録

Herokuダッシュボード > Resourcesタブ > Add-ons > Heroku Scheduler > Add Job をクリック

TIPS

・Using CarrierWave で上手くいかなかったのは、CarrierWave側のバグのせいっぽい。

CarrierWave のストレージに fog を使い、S3にファイルを保存したい際に uninitialized constant CarrierWave::Storage::Fog というエラーが出る場合の対処 - Qiita
問題 CarrierWave のストレージに fog を使い、保存先を Amazon S3 にしたい場合、 CarrierWave のドキュメント carrierwaveuploader/carrierwave の設定を参考に...

・デフォルトではpublic以下にsitemap.xml.gzが作成されるのをtmp/に変更している。

・Rubyのコードで検索エンジンにsitemapをマニュアルで知らせる方法もある。

SitemapGenerator::Sitemap.ping_search_engines("https://s3-ap-northeast-1.amazonaws.com/#{ENV['AWS_S3_BUCKET']}/sitemaps/sitemap.xml.gz")

・sitemap.rbのSitemapGenerator::Sitemap.sitemaps_host = “https://s3-ap-northeast-1.amazonaws.com/#{ENV[‘AWS_S3_BUCKET’]}/”の最後の’/’は必須。ping(検索エンジンへの通知)の実行時にバケット名が認識されなくなり、通知されなくなってしまう。

試してみた時のログ
Pinging with URL 'https://s3-ap-northeast-1.amazonaws.com/sitemaps/sitemap.xml.gz':
   Successful ping of Google
   Successful ping of Bing

・rails sitemap:refresh:no_ping とすると、sitemapを作成するだけで検索エンジンへの通知は行わない。

感想

さくっとできなかったと冒頭に述べたが、その理由は、ローカルでガリガリ進めていたためHerokuの書き込みできない仕様を忘れていたことと、Using CarrierWaveで進めていて全然できなかったことである。
これを読んだ方が、私ががはまったポイントにハマらないといいなと思います。もちろん未来の自分も。

コメント