Rails
es6
vue.js
laravelMix

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

What・Why?

Laravel Mixとは?

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

なぜ Laravel Mixなのか?

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

なぜwebpackを直接使わないのか?

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

この記事の各Version

  • Rails 5.2.0
  • Ruby 2.5.0
  • node 9.11.2
  • yarn 1.7.0
  • laravel-mix ^2.0

導入編

Laravel Mixを設定する

Laravel Mixに必要ファイルをLaravelのリポジトリからコピーする

publicPathを設定する

webpack.mix.js

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');

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

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

.gitignore

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

を追記する。

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

$ brew install nodejs
$ npm install -g yarn

docker環境の場合こちらを参考にしてください

node_modules のインストール

$ yarn install

Assets compile(development)

$yarn run dev

1_____Development_ghq_github_com_saboyutaka_rails-laravel-mix__zsh_.png

public/mix-manifest.json

{
    "/js/app.js": "/js/app.js",
    "/css/app.css": "/css/app.css"
}

production用にversioningする

# webpack.mix.js
let mix = require('laravel-mix');

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

+ # productionの時はversioningする    
+ if (mix.inProduction()) {
+   mix.version();
+ }

Assets Compile(production)

$ yarn run prod

1_____Development_ghq_github_com_saboyutaka_rails-laravel-mix__zsh_.png

public/mix-manifest.json

{
    "/js/app.js": "/js/app.js?id=c1d308b8f13f8ce146b7",
    "/css/app.css": "/css/app.css?id=943ad87b58616383f50a"
}

versioning, minifyされてる

Rails側での対応

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

ヘルパーを用意する

app/helpers/laravel_mix_helper

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

app/views/application.html.erb

<!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/app.js') %>"></script>
</head>

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

templateにVue Componentを追記してみる

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

表示させてみる

App.png

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

Laravel MixのAPI

https://github.com/JeffreyWay/laravel-mix/blob/master/setup/webpack.mix.js

// Full API
// mix.js(src, output);
// mix.react(src, output); <-- Identical to mix.js(), but registers React Babel compilation.
// mix.preact(src, output); <-- Identical to mix.js(), but registers Preact compilation.
// mix.coffee(src, output); <-- Identical to mix.js(), but registers CoffeeScript compilation.
// mix.ts(src, output); <-- TypeScript support. Requires tsconfig.json to exist in the same folder as webpack.mix.js
// mix.extract(vendorLibs);
// mix.sass(src, output);
// mix.standaloneSass('src', output); <-- Faster, but isolated from Webpack.
// mix.fastSass('src', output); <-- Alias for mix.standaloneSass().
// mix.less(src, output);
// mix.stylus(src, output);
// mix.postCss(src, output, [require('postcss-some-plugin')()]);
// mix.browserSync('my-site.test');
// mix.combine(files, destination);
// mix.babel(files, destination); <-- Identical to mix.combine(), but also includes Babel compilation.
// mix.copy(from, to);
// mix.copyDirectory(fromDir, toDir);
// mix.minify(file);
// mix.sourceMaps(); // Enable sourcemaps
// mix.version(); // Enable versioning.
// mix.disableNotifications();
// mix.setPublicPath('path/to/public');
// mix.setResourceRoot('prefix/for/resource/locators');
// mix.autoload({}); <-- Will be passed to Webpack's ProvidePlugin.
// mix.webpackConfig({}); <-- Override webpack.config.js, without editing the file directly.
// mix.babelConfig({}); <-- Merge extra Babel configuration (plugins, etc.) with Mix's default.
// mix.then(function () {}) <-- Will be triggered each time Webpack finishes building.
// mix.extend(name, handler) <-- Extend Mix's API with your own components.
// mix.options({
//   extractVueStyles: false, // Extract .vue component styling to file, rather than inline.
//   globalVueStyles: file, // Variables file to be imported in every component.
//   processCssUrls: true, // Process/optimize relative stylesheet url()'s. Set to false, if you don't want them touched.
//   purifyCss: false, // Remove unused CSS selectors.
//   uglify: {}, // Uglify-specific options. https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
//   postCss: [] // Post-CSS options: https://github.com/postcss/postcss/blob/master/docs/plugins.md
// });

React, TypeScript, PostCSS, Stylus どれも速攻で環境つくれます。

まとめ

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

参考のRailsアプリケーション

https://github.com/saboyutaka/rails-laravel-mix