Sinatra+Vue.jsでSPAを作っていきます。
以前の記事で「webpack-dev-serverのproxy使えば?」とコメント頂きましたので、それを受けて全面的に書き直しました。(Thank you @nak1114)
完成したコードはこちらで見ることができます。
フロントエンドの準備
yarnを使うので、インストールしていない人はインストールしてください。
vue-cliを使うのでインストールします。
$ yarn global add vue-cli
vue templateを使います。
$ vue init isuke/vuejs-template#v1.0.0 sinatara-vue-sample
isuke/vuejs-template
は著者が、公式のvuejs-templates/webpack-simple
をもとに作ったvue.jsのテンプレートです。
大分改造してあるので原型がおぼろげです。
vue init
したら指示に従って以下のコマンド実行します。
$ yarn install
$ yarn run dev
http://localhost:8080/ をブラウザで開いてみましょう(といか勝手に開きます)。
一行もコードを書かずにこれだけでwebページができていることがわかると思います。
[Bye]リンクをクリックしてページ遷移ができていることも確認してみてください。
サーバーサイドの作成
ここからsinatraを使っていきます。
$ bundle init
# frozen_string_literal: true
source "https://rubygems.org"
ruby '2.4.1'
gem 'sinatra'
gem 'sinatra-contrib'
$ bundle install --path=vendor/bundle
sinatraのコードを書いていきます。
require 'sinatra/base'
require "sinatra/reloader"
class Server < Sinatra::Base
configure :development do
register Sinatra::Reloader
end
get '/companies.json' do
companies = []
1.upto(50) do |i|
companies << {
id: i,
name: "Company #{i}"
}
end
companies.to_json
end
end
require './server'
run Server
何の変哲もない APIが一つあるだけです。
立ち上げて、確認してみましょう。
$ bundle exec rackup
jsonが返ってきました。
次のステップに進みましょう。
フロントとサーバーの連携
フロントはnpm run dev
でlocalhost:8080
サーバーはbundle exec rackup
でlocalhost:9292
にそれぞれアクセスできるようになりました。
これをくっつけましょう。
webpack.config.cofffee
に以下の行を追加します。
else
config = merge baseConfig,
output:
filename: 'build.js'
devtool: '#eval-source-map'
devServer:
contentBase: 'dist'
historyApiFallback: true
noInfo: true
+ proxy:
+ "/api":
+ target: "http://localhost:9292"
+ pathRewrite: {"^/api" : ""}
performance:
hints: false
module.exports = config
サーバーを2つとも立ち上げて http://localhost:8080 を見てみましょう。
$ bundle exec rackup
$ yarn dev
ここでトップページが見れたらOKです。
さて、これでフロントからAPIが叩けるようになったので、ちょっと試してみましょう。
Bye.vueを以下のように書き換えます。
<template lang="pug">
.bye
button(@click="load") load
ul(v-for="company in companies")
li {{company.name}}
router-link(:to="{ name: 'top'}") TOP
</template>
<script lang="coffee">
export default
data: ->
companies: []
methods:
load: ->
axios.get('/api/companies.json')
.then (responce) =>
@companies = responce.data
</script>
[load]ボタンをおしてデータが表示されればOKです。
ついでにHot Module Replacementが動作しているかもためしてみましょう。
Compnayデータが表示された状態でBye.vue
のstyleを適当に変えてみてください。
.bye
-webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale
text-align: center
margin-top: 60px
+ background-color: red
h1
font-weight: normal
a
color: #42b983
ブラウザを更新せずに反映されたら成功です。
Hot Module Replacementが動作しています。
Productionモードで動かす
最後にProductionでの動かし方です。
まずyarn run build
を実行してsrc
ディレクトリの中をコンパイルします。
コンパイルした結果はdist
に吐かれます。
$ yarn run build
次に、静的ファイル配信用のサーバーを作ります。
require 'sinatra/base'
class Static < Sinatra::Base
configure :production do
set :public_dir, File.join(settings.root, 'dist')
end
get '/' do
send_file File.join(settings.public_dir, 'index.html')
end
end
dist
ディレクリをpublicとして公開するディレクトリに指定しています。
また、/
にアクセスしたときに、'dist/index.html'を返しています。
static.rb
を使うようにconfig.ru
を改良しましょう。
+ require './static'
require './server'
+ if ENV["APP_ENV"] == "production"
+ run Rack::URLMap.new(
+ '/' => Static,
+ '/api' => Server,
+ )
+ else
run Server
+ end
あとは環境変数をつけて実行してあげるだけです。
$ APP_ENV=production bundle exec rackup
以上です。お疲れ様でした。