LoginSignup
6
7

More than 5 years have passed since last update.

Sinatra+Vue.jsでSPA(Hot Module Replacementつき) Take 2

Last updated at Posted at 2017-11-05

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
Gemfile
# frozen_string_literal: true

source "https://rubygems.org"

ruby '2.4.1'

gem 'sinatra'
gem 'sinatra-contrib'
$ bundle install --path=vendor/bundle

sinatraのコードを書いていきます。

server.rb
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
config.ru
require './server'

run Server

何の変哲もない APIが一つあるだけです。

立ち上げて、確認してみましょう。

$ bundle exec rackup

jsonが返ってきました。
次のステップに進みましょう。

フロントとサーバーの連携

フロントはnpm run devでlocalhost:8080
サーバーはbundle exec rackupでlocalhost:9292
にそれぞれアクセスできるようになりました。
これをくっつけましょう。

webpack.config.cofffeeに以下の行を追加します。

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

次に、静的ファイル配信用のサーバーを作ります。

static.rb
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を改良しましょう。

cofig.rb
+ 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 

以上です。お疲れ様でした。

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7