rails

DockerでVue on Rails

Vueの双方向データバインディングやコンポーネントベースのフロント開発に慣れると、Rails + jQueryでは満足できない体になる。
Webpackerじゃなくてwebpackでよくねみたいな意見があるが、本記事では折角なのでWebpackerでやっていく。

Rails+Dockerでwebpackなしの環境構築

環境構築

webコンテナに渡すGemfileとGemfile.lockを作成。

$touch Gemfile Gemfile.lock

Gemfileの中身に以下を記述。lockは空でいい。

source 'https://rubygems.org'
gem 'rails', '~>5'

docker-compose.ymlとDockerfileはそれぞれこんな感じに。

  • docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7.19
    environment:
      - MYSQL_ROOT_PASSWORD=root
    ports:
      - "3307:3306"
    volumes:
      - ./tmp/db:/var/lib/mysql
  webpacker:
    build: .
    command: bundle exec bin/webpack-dev-server
    volumes:
      - .:/myapp
    ports:
      - "3035:3035"
  web:
    build: .
    environment:
      RAILS_ENV: development
    command: bash -c "bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
      - bundle-data:/usr/local/bundle
    ports:
      - "3000:3000"
    depends_on:
      - db
      - webpacker
volumes:
  bundle-data:

  • Dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev

RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
  && apt-get install -y nodejs

RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn

RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

CMD ["rails", "server", "-b", "0.0.0.0"]

下記コマンドを実行する。

docker-compose run web rails new . --force --database=mysql --webpack=vue --skip-coffee
sed -i ".bak" -e "s/host: localhost/host: webpacker/g" config/webpacker.yml
docker-compose build
docker-compose run web rails db:create
docker-compose up

自分がやった時は以下のように怒られた。rails newで–webpack=vueを指定するとこの辺はうまくやってくれるのかと思っていた。

webpacker_1  | internal/modules/cjs/loader.js:584
webpacker_1  |     throw err;
webpacker_1  |     ^
webpacker_1  |
webpacker_1  | Error: Cannot find module 'webpack'

webpacker:install系のコマンドを打つとモジュールがインストールされる。

docker-compose run web rails webpacker:install
docker-compose run web rails webpacker:install:vue
docker-compose build
docker-compose up

webpackのビルドが終わったよー的なログが出てからlocalhost:3000にアクセスするとyayが見れる。

Vueの画面を表示するまで

app/javascript/app.vueを見るとこんな感じになっている。

<template>
  <div id="app">
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      message: "Hello Vue!"
    }
  }
}
</script>

<style scoped>
p {
  font-size: 2em;
  text-align: center;
}
</style>

これを表示するために以下のようにファイルを変更していく。
config/routes.rb

Rails.application.routes.draw do
  root to: 'home#index'
end

app/controllers/home_controller.rb

class HomeController < ApplicationController
  def index
  end
end

app/views/home/index.html.erb

<%= javascript_pack_tag 'hello_vue' %>

これでlocalhost:3000を見に行くとHello vueになっているはず。

ActiveRecordが使える分nuxtよりrails+vue構成のほうが便利かもしれない…

TypeScript導入

折角なので流行のTypeScriptでvueを書いていく。

$ docker-compose run web rails webpacker:install:typescript

app/javascript/packs/hello_vue.jsをhello_vue.tsにリネーム。
app/javascript/app.vueのscriptタグにtsを指定。
app/javascript/app.vue

(略)
<script lang="ts">
(略)

VSCodeだとこの時点でエラーが出るので、ts-loaderがvueファイルも見るようにする
config/webpack/loaders/typescript.js

module.exports = {
  test: /\.(ts|tsx)?(\.erb)?$/,
  use: [
    {
      loader: 'ts-loader',
      options: {
        appendTsSuffixTo: [/\.vue$/]
      }
    }
  ]
}

Vueの型定義ファイルを追加して完了。

app/javascript/types/vue.d.ts

declare module "*.vue" {
    import Vue from 'vue'
    export default Vue
}