Vue.js+Webpackを導入したRails環境をdockerで構築してみる【part1】

#はじめに
学習をする中での備忘録。
やることはタイトル通り。
**※注意**
これまでバックエンドを1ヶ月半ほど、フロントを3ヶ月半ほど勉強した初学者です。
内容に間違い/不合理な点などある可能性が高いです。
アドバイスや間違いの指摘など頂けると嬉しいです。

#ステップ1. dockerイメージの構築からRailsサーバ起動まで
まずはdocker+Railsの環境を整える。
・dockerインストール済み
・dbはmysql
・rails:5.2.3
・ruby:2.5.1
・sprocketsは削除せず、アセットパイプラインを使用

その他詳しい解説などは省く。

####それ用のディレクトリを任意の場所に用意
```
mkdir test
```

####配下に以下の4ファイルを作成
```ruby:Gemfile
source 'https://rubygems.org'
#　バージョンは適宜指定
gem 'rails', '5.2.3'
```
```text:Dockerfile
FROM ruby:2.5.1
RUN apt-get update -qq && apt-get install -y build-essential nodejs
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app
```
```yml:docker-compose.yml
version: '3'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true
  db:
    image: mysql:5.7
    volumes:
      - db-volume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
volumes:
  db-volume:
```
```ruby:Gemfile.lock
#　空ファイル
```

####Railsプロジェクトを作成
```terminal:/test
docker-compose run web rails new . --force --database=mysql --skip-turbolinks
```
forceでGemfile等を上書き、turbolinksは使わないのでskip
####dockerイメージを再構築
```terminal:/test
docker-compose build
```
→Gemのインストールや作成されたRailsプロジェクトのファイル群をコンテナ内に取り込むために必要。

####database.ymlを編集
```yml:test/config/database.yml
...
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  #　以下二行をmysql用に書き換え
  password: password
  host: db

development:
  <<: *default
  database: app_development
...
```
passwordはMYSQL_ROOT_PASSWORD環境変数の"password"
hostはMySQLサーバのコンテナのサービス名である"db"

####コンテナの起動と確認
・コンテナ起動

```terminal:/test
docker-compose up
```
起動が確認できたら一旦停止してください。

####データベースを作成
```terminal:/test
docker-compose run web bundle exec rails db:create
```
####ローカルサーバへのアクセス確認
再度コンテナを起動し、ローカルサーバにアクセスする

```terminal:/test
docker-compose up
```
→http://localhost:3000 へ飛びRailsサーバの起動を確認

#ステップ2. Webpack+Vue.jsの導入

####Webpackとパッケージのインストール

まずはRailsのルートディレクトリ(test)に/frontendを作成、移動

```terminal:/test
mkdir frontend
cd frontend
```
package.jsonを作成（設定はデフォルト値）

```terminal:/frontend
yarn init
```
必要なパッケージ達をインストール

```terminal:/frontend
yarn add vue webpack webpack-cli vue-loader vue-template-compiler css-loader style-loader babel-loader @babel/core @babel/preset-env sass-loader node-sass --save
```

####webpack.config.jsの作成
`/frontend/config/development/webpack.config.js`
`/frontend/config/production/webpack.config.js`
の2つを作成。

```terminal:/frontend
mkdir config
mkdir config/development
mkdir config/production
touch config/development/webpack.config.js
touch config/production/webpack.config.js
```

####エントリーポイントとなるフォルダの作成
`/frontend/src/javascripts/entry.js`を作成します。

```terminal:/frontend
mkdir src
mkdir src/javascripts
touch src/javascripts/entry.js
```

####各種設定ファイルの編集
**・development環境用の設定ファイルを編集**
※ test/app/assets/javascript配下に出力されるようoutputパスを書き換えてください

```js:/frontend/config/development/webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    devtool: 'inline-source-map',
    mode: 'development',
    entry: {
        webpack: './src/javascripts/entry.js'
    },
    output: {
        // /app/assets以下に出力するよう、path:のキーを絶対パスで書き換え
        path: 'ここを書き換え/test/app/assets/javascripts',
        filename: '[name].js'
    },
    module: {
    rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader'
        },
        {
            test: /\.vue$/,
            loader: 'vue-loader'
        },
        {
            test: /\.css$/,
            use: ['vue-style-loader', 'css-loader']
        },
        {
            test: /\.scss$/,
            use: [
                'vue-style-loader',
                'css-loader',
                {
                loader: 'sass-loader',
                },
            ],
        }
    ]
    },
    resolve: {
        extensions: ['.js', '.vue'],
        alias: {
            vue$: 'vue/dist/vue.esm.js',
        },
    },
    plugins: [
        new VueLoaderPlugin()
    ]
}
```

**・production環境用の設定ファイルを編集**
※ development同様、outputパスを書き換えてください

```js:/frontend/config/production/webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    mode: 'production',
    entry: {
    webpack: './src/javascripts/entry.js'
    },
    output: {
        // 書き換え
        path: '書き換え/test/app/assets/javascripts',
        filename: '[name].js'
    },
    module: {
        rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
            presets: [
                "@babel/preset-env"
            ]
            }
        },
        {
            test: /\.vue$/,
            loader: 'vue-loader'
        },
        {
            test: /\.css$/,
            use: ['vue-style-loader', 'css-loader']
        },
        {
            test: /\.scss$/,
            use: [
            'vue-style-loader',
            'css-loader',
            {
                loader: 'sass-loader',
            },
            ],
        }
        ]
    },
    resolve: {
        extensions: ['.js', '.vue'],
        alias: {
            vue$: 'vue/dist/vue.esm.js',
        },
    },
    plugins: [
        new VueLoaderPlugin()
    ],
}
```

####ビルド用コマンドの追加
`frontend/package.jsonに`以下を追記。

```json:frontend/package.json
  "scripts": {                    
    "release": "webpack --config config/production/webpack.config.js",             
    "build": "webpack --config config/development/webpack.config.js",              
    "watch": "webpack --watch --config config/development/webpack.config.js"       
  },
```

ここまででVueを動かす環境と、Webpackを用いてバンドルファイルをビルドする準備が完了。
最後に、動作確認のため以下の作業を行う。

#ステップ3. ここまでの動作確認

####必要なファイルの準備
適当なコントローラを作る

```terminal:/frontend
cd ..
docker-compose run web bundle exec rails g controller tests
```

コントローラとルートを編集

```rb:/app/controllers/tests_controller.rb
def index
end
```

```rb:/config/routes.rb
# 追加
resources :tests
```
ビューを作成

```erb:/app/views/tests/index.html.erb
<div id="app">
  <p>{{name}}</p>
</div>
```
Vueを書く

```js:/frontend/src/javascripts/entry.js
import Vue from 'vue';

document.addEventListener("DOMContentLoaded", function(event) {
  new Vue({
    el: '#app',
    data: {
      name: '動作しています'
    }
  });
});
```

####ビルドの実行
(frontend配下に移動)

```terminal:/frontend
yarn run build
```

####動作確認
http://localhost:3000/tests にアクセスし、'動作しています'と表示されていれば完了。

###補足

gem 'ruby-sass'