どうも、Ruby on Railsで作成したWebアプリを公開するためのレンタルサーバーがRails非対応だったのに契約してから気づいたバカです。
幸い、動的コンテンツをほとんど含まないアプリだったため、静的なHTMLファイルに変換してサーバーにアップロードするとかいうゴリ押しで公開までこじつけたので、やり方を記しておきます。
参考サイト様(Qiita) : Rails で作成した画面を静的に出力する
目次
ローカル環境
- macOS High Sierra 10.13.6
- Ruby 2.4.2
- Rails 5.1.4
サーバーはRubyを使わず、HTMLを配信するだけなので環境は関係ないと思いますが、一応ロリポップのレンタルサーバーです。
(Railsは動きませんがコスパと機能性のバランスが良くて初めての人におすすめのレンタルサーバーです。SSHも使えるし勉強にもいい)
Turbolinks, Asset Pipelineの一部機能を無効にする
Railsの便利機能であるこの2つの機能ですが、今回は邪魔にしかならないので無効にします。
# Assetのファイル名にフィンガープリントを付与しない config.assets.digest = false # JSとCSSの圧縮を有効にする config.assets.js_compressor = Uglifier.new(:harmony => true) config.assets.css_compressor = :sass
//= require turbolinks
gem 'turbolinks', '~> 5'
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
bundle install
“turbolinks:load”などのイベントを利用していた場合は、DOMContentLoadedやjQueryのreadyなどに置き換えます。
静的ファイルの出力スクリプトを書く
ほとんど参考サイト様のコピーですが、いくつか変更点があります。
require 'open-uri' HOST = "http://localhost:3000" # ここにサイトのURLを入れる DEST = "http://example.com" def output_html(array) for path in array url = HOST + path open(url) do |html| path = (path == "/") ? "/index.html" : path # 変更点1 file_path = Dir.pwd + "/html" + path + (path.end_with?("/") ? "index.html" : ""); file_dir = File.split(file_path)[0] FileUtils.mkdir_p(file_dir) unless FileTest.exist?(file_dir) open(file_path, "w+b") do |file| file.write(html.read.gsub!(%r(http://(localhost|0.0.0.0|127.0.0.1):3000), DEST)) # 変更点2 end end end end # ここで出力したいURLの一覧の array を作成するだけ # いっぱいある時はfor文とかeachとか使う # フォルダ指定する時は最後に/つける array = Array.new array.push "/" array.push "/comic/2/" array.push "/comic/3/" array.push "/comic/5/" array.push "/comic/6/" # 変更点3 array.push "/assets/application.js" array.push "/assets/application.css" output_html(array)
変更点1. URLがディレクトリを指している場合、そのディレクトリの中のindex.htmlというファイルに出力しています。 (これにより、参考サイトのようにURL設計を変更する必要が無くなります)
変更点2. HTMLソース中の、”http://localhost:3000″ “http://0.0.0.0:3000” などの文字列を正規表現を使って本番環境のURLに置き換えています。
変更点3. 圧縮済みのJSとCSSもHTMLと同じ方法で出力しています。 (環境によってJS,CSSのパスが違う可能性があるので、出力されたHTMLに書いてあるパスを確認します)
スクリプトファイルができたら、ターミナルのウィンドウを2個用意し、”rails s”でサーバーを起動した後、もう一つのウィンドウで”ruby output.rb”と打てば、htmlというディレクトリが作成され、その中にHTMLファイルが出力されます。
出力されたHTMLはFTPやWebDAV、rsyncなどでサーバーにアップロードします。
画像などのアセットを配置
出力されたHTMLのソースを確認すると画像は”/assets/folder/xxx.png”というファイルを参照するようになっています。(環境によって違うかもしれません)
HTMLからそれらを参照できるようにサーバーのディレクトリを整理して、画像をアップロードします。
(場合によってはhtml.erbの方を編集し、再度output.rbでHTMLを出力することも検討します)
.htaccess でリダイレクトの設定
“http://example.com/” “http://example.com/index.html” 両方のURLでアクセスできてしまい、このままでは検索エンジンからの評価が良くないらしいので、index.htmlをURLに含めない方に統一するためにリダイレクトの設定を行います。
ロリポップのサーバーのWEBサーバはApacheなので、.htaccessファイルで設定します。
RewriteEngine On RewriteBase / RewriteRule ^(.*)index.*$ /$1 [R=301,L]
デプロイ自動化スクリプト
FTP経由でもいいと思いますが、rsyncコマンドが有能という話を聞き、しかもロリポップのサーバーはsshに対応しているのでrsyncを採用します。
まずはsshの接続先をconfigファイルに登録しておきます。
参考1. 【 rsync 】コマンド(その1)――ファイルやディレクトリを同期する:Linux基本コマンドTips(82) – @IT
参考2. ~/.ssh/configについて
参考3. ssh の設定ファイルを使って rsync で簡単にファイル転送
# ssh接続先にserverという名前をつける Host server HostName example.com IdentityFile ~/.ssh/id_rsa User username Port 9999
#!/bin/bash cd `dirname $0` # このファイルを配置したディレクトリに移動 DIR=$(cd $(dirname $0); pwd) # このファイルを配置したディレクトリを変数DIRに入れる rails s -d # railsのサーバーをバックグラウンドで起動 ruby output.rb # HTML出力スクリプトを実行 kill -9 `cat tmp/pids/server.pid` # railsのサーバーを終了させる # 画像などのアセットのシンボリックリンクをHTMLから参照できるパスに配置 ls app/assets/images | xargs -I{} ln -s $DIR/app/assets/images/{} html/assets/ # rsync コマンドを用いてhtmlディレクトリをサーバと同期 # コマンドのパラメータやオプションなどは調べておくことを推奨 # 今回は~/.ssh/configに設定したserverという接続先と同期している rsync -acvL html/ server:~/web/ rm -r html exit 0
おわりに
こうしてできたWebサイトがこちらです → ミリシタ譜面ビューア
AWS 無料枠からの移転ですが、RubyやDBでの処理が減った分レスポンスが早くなった気がするような気がするような気がします。
その代わりTurbolinkを無効化したので画面遷移の無駄が増えてるはずですが、それを加味してもパフォーマンスは良くなっていると思います。
(なによりレンタルサーバーは落ちた時に備えてインスタンスをもう一つ用意しておくとか落ちた時の再起動とか自分で全部やらなくていいので楽)
Assetにフィンガープリントを付与する機能を切った関係で次にJS, CSS周りをいじる時にキャッシュ問題が発生しそうなので、次はその記事も書きたいと思います。
言語的にはRuby, Pythonが好きなんですが、PHPとは違って安いサーバーで稼働させようと思った時に支障が出てくるのが難点ですね。
PHPも書けるので次からはLaravelでアプリを作ろうと思います。
test comment