RailsでLaravel Mix(webpack)を使って15分でES6を書きはじめる

## What・Why?
### Laravel Mixとは？

![Laravel_Mix.png](https://qiita-image-store.s3.amazonaws.com/0/28262/d9c80758-db9d-31b3-6e6c-64315b023146.png)

- https://laravel-mix.com
- https://github.com/JeffreyWay/laravel-mix
- webpackのWrapper API
- LaravelのAssets Compileの機能
- Node.js のライブラリ、PHPを必要としない
- RailsでもSinatraでもHanamiでもDjangoでもEchoでもWordpressでも、もちろんLaravelでも使える

### なぜ Laravel Mixなのか?
- RailsのSprockets、AssetsPipelineを使いたくない
  - Too fu*kin' outdated
  - CoffeeScript....?
  - Turbolinksハマる
- webpacker使いたくない
  - RubyのRuntimeで動いてるのがダサい
  - 設定がなぞ
  - ディレクトリがなぞ
  - .js.erb とかやりがち
  - 結局フロントエンドエンジニアに迷惑かける

### なぜwebpackを直接使わないのか?
- webpackを使って開発はじめるまでに設定ファイルをたくさん書くのが大変
- シュッと環境整備してES6やTypeScript使いたい
- 15分でes6書きたい

### Rails, Laravel Mix で構成しているRailsアプリ
https://github.com/saboyutaka/rails-laravel-mix

### この記事の各Version
* Rails 5.2.0
* Ruby 2.5.1
* node 9.11.2
* yarn 1.7.0
* laravel-mix ^4.0.7

## 事前準備

### npm, yarnのインストール(macOS ver)

```bash
$ brew install nodejs
$ npm install -g yarn
```

docker環境の場合[こちら](https://github.com/saboyutaka/rails-laravel-mix/blob/master/docker-compose.yml)を参考にしてください
    


### node_modules のインストール
`$ yarn install`


## Laravel Mix 導入編

### Laravel Mixに必要なファイルを取得する

Laravel Mixに必要ファイルを[Laravelのリポジトリ](https://github.com/laravel/laravel)からコピーする

```
- webpack.mix.js
- package.json
- resources
    - js
        - components
            - ExampleComponent.Vue
        - app.js
        -  bootstrap.js
    - sass
        - app.scss
        - _variables.scss
```

### Laravel Mixの設定

#### publicPathを設定する

webpack.mix.js

```diff
let mix = require('laravel-mix');

+ mix.setPublicPath('public').
+ js('resources/assets/js/app.js', 'public/js')
- mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
```

setPublicPathを設定することで、`mix-manifest.json` がpublicフォルダに吐き出されるようになる。こちらの方が都合がいいので変更する。

#### .gitignoreにLaravel Mixの設定を追加する

.gitignore

#### 
```diff
+ public/css/app.css
+ public/js/app.js
+ public/js/manifest.js
+ public/js/vendor.js
+ public/mix-manifest.json
```

を追記する。

## Laravel Mix を動かす
```
$ yarn run dev
```
<img width="658" alt="1_____Development_ghq_github_com_saboyutaka_rails-laravel-mix__zsh_.png" src="https://qiita-image-store.s3.amazonaws.com/0/28262/490d13ff-2b4d-3a33-8b0d-4c15a1b2ee6a.png">

* public/js/app.js
* public/js/manifest.js
* public/js/vendor.js
* public/css/app.css
* public/mix-manifest.json

が生成される。

## Rails側での変更

### ヘルパーを用意する

LaravelMixによってpublicフォルダーにコンパイルされたcssとjsが吐き出される。また `mix.version()` を使用した場合、 `mix-manifest.json` にファイルのハッシュ値が記録されているので、RailsのView側でハッシュを利用したURLを生成するヘルパーを用意する。

app/helpers/laravel_mix_helper.rb

```ruby
module LaravelMixHelper
  class LaravelMixError < StandardError; end
  MANIFEST_FILE = 'public/mix-manifest.json'

  def mix(path)
    unless File.exists?(MANIFEST_FILE)
      raise LaravelMixError.new('The Mix manifest does not exist. Run `yarn run dev`.')
    end

    manifest = JSON.parse(File.read(MANIFEST_FILE))
    asset_path(manifest[path])
  end
end
```

### View側でhelperを利用する

app/views/application.html.erb

```diff
<!DOCTYPE html>
<html>
<head>
    <title>App</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

+     <link rel="stylesheet" href="<%= mix('/css/app.css') %>">
+     
+     <script src="<%= mix('/js/manifest.js') %>"></script>
+     <script src="<%= mix('/js/vendor.js') %>"></script>
+     <script src="<%= mix('/js/app.js') %>"></script>
</head>

<body>
<%= yield %>
</body>
</html>
```

### templateにVue Componentを追記してみる

app/views/top/index.html.erb(サンプル)

```diff
+ <div id="app">
+   <example-component />
+ </div>
```

## 表示させてみる

<img width="778" alt="App.png" src="https://qiita-image-store.s3.amazonaws.com/0/28262/a53aeb63-622c-9835-4127-ee86e4ada438.png">


Laravel Mixのデフォルトで用意されたES6で書かれたVue.jsのコンポーネントを表示することが出来ました。versioningも正しく出来てます。

## まとめ

![rails-laravel-mix____Development_src_github_com_saboyutaka_rails-laravel-mix__-_____Gemfile__rails-laravel-mix_.png](https://qiita-image-store.s3.amazonaws.com/0/28262/a2a88b4e-d75c-3c24-0be4-3d3c40344dd3.png)

Laravel Mixを使ってRailsからフロントエンド向けのGemを外すと `rails new` のGemfileから必要なgemが実質4つになる。最高。

Laravel Mixを使ってRailsでも簡単に最新のフロントエンド環境構築してみてはいかがでしょうか？？