現在 日本 ノマド 中!!

[Rails] Webpacker の使い方

Rails 6から Webpacker という Webpack のラッパーライブラリがデフォルトでパッケージ化されました。

ここでは、 Webpacker の利用方法について紹介していきます。

目次

Webpacker とは

Webpack を Ruby on Rails で使うための gem パッケージです。

Webpack とは JavaScript, CSS, 画像などの静的ファイルを1つにまとめて管理するためのモジュールバンドラーで、node.jsのモジュールの1つです。

Rails アプリケーションを新規作成したとき、以下のファイルが Webpacker の関連ファイルになります。

ディレクトリ構造

app
  /app/javascript
    /channels
      /consumer.js
      /index.js
    /packs
      /application.js
  /bin
    /webpack
    /webpack-dev-server
  /config
    /webpack
      /development.js
      /environment.js
      /production.js
      /test.js
    /webpacker.yml

channels ディレクトリは、Rails の Action Cable コンポーネントによって生成されます。

packs ディレクトリは、webpack用のエントリーポイントが含まれています。

app/javascript/packs/application.js にはデフォルトで Active Storage や Action Cable 、Turbolinks 、Rails-UJS を読み込む処理が含まれています

app/javascript/packs/application.js

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

config/webpacker.yml について

webpacker.yml は、 webpack の webpack.config.js に相当します。

webpacker.yml

# Note: You must restart bin/webpack-dev-server for changes to take effect

default: &default
  source_path: app/javascript
  source_entry_path: packs
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/webpacker
  check_yarn_integrity: false
  webpack_compile_output: true

  # Additional paths webpack should lookup modules
  # ['app/assets', 'engine/foo/app/assets']
  resolved_paths: []

  # Reload manifest.json on all requests so we reload latest compiled packs
  cache_manifest: false

  # Extract and emit a css file
  extract_css: false

  static_assets_extensions:
    - .jpg
    - .jpeg
    - .png
    - .gif
    - .tiff
    - .ico
    - .svg
    - .eot
    - .otf
    - .ttf
    - .woff
    - .woff2

  extensions:
    - .mjs
    - .js
    - .sass
    - .scss
    - .css
    - .module.sass
    - .module.scss
    - .module.css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg

development:
  <<: *default
  compile: true

  # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
  check_yarn_integrity: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    pretty: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: '**/node_modules/**'


test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Extract and emit a css file
  extract_css: true

  # Cache manifest.json for performance
  cache_manifest: true

デフォルトでは、development, test, production の3種類の環境に分けて設定をコントロールすることができるようです。

また、すべての環境で default 設定情報を読み込んでいます。

default 設定項目について以下のとおりです。

source_pathソースのルートパス。(例: app/javascript = APP/app/javascript)
source_entry_pathエントリーポイントのパス。(例: packs = source_path/packs = APP/app/javascript/packs)
public_root_pathコンパイル出力先ルートパス。(例: public = APP/public)
public_output_pathコンパイル出力先パス。(例: packs = public_root_path/packs = APP/public/packs)
cache_path再コンパイル時間を改善するためにキャッシュファイルを書き込みます。
check_yarn_integrityローカルの全ての JavaScript パッケージが最新であるかチェックします。
webpack_compile_outputコンパイル出力有無。
resolved_pathswebpack が読み込む先パスの追加オプション。
cache_manifestmanifest.json の読み込み有無。
extract_cssCSS ファイルの抽出 / 出力有無。
static_assets_extensionswebpack は JavaScript モジュールとしてメモリにロードする代わりに、その名前のファイルを出力します。
extensionswebpack が認識するファイル拡張子のリスト。

Demo ページを作成

デモ用のコントローラーとビューを作成します。

ターミナル

$ rails generate controller Hello index
Running via Spring preloader in process 86718
      create  app/controllers/hello_controller.rb
       route  get 'hello/index'
      invoke  erb
      create    app/views/hello
      create    app/views/hello/index.html.erb
      invoke  test_unit
      create    test/controllers/hello_controller_test.rb
      invoke  helper
      create    app/helpers/hello_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/hello.scss

後ほど、 app/views/hello/index.html.erb を編集します。

エントリーポイントファイル, JavaScript, CSS, 画像ファイルを用意

はじめに、JavaScript, CSS, 画像を格納するディレクトリを作成します。

ターミナル

$ cd app/javascript/
$ mkdir js css images

デフォルトのエントリーポイントを編集します

すべてのページに読み込むための js, css を設定します。

packs/application.js

...
import '../js/application'
import '../css/application'
const images = require.context('../images', true)
...

js/application.js と css/application.[s]css と images ディレクトリ配下の画像を読み込むように設定しています。

Javascriptについて、すべてのページに読み込む共通の js と特定のビュー hello/index.html.erb にのみ読み込む js を作成します。

- js/application.js: すべてのページに読み込む共通の js。

- js/hello_world.js: js/application.js に読み込まれます。

- js/hello.js: 特定のビュー hello/index.html.erb にのみ読み込む js。

js/application.js

import hello_world from './hello_world'
hello_world();

js/hello_world.js

export default () => {
    window.onload = () => {
        document.getElementsByTagName("H1")[0].innerText = 'Hello World';
    }
}

js/hello.js

console.log('hello');

CSSについて、すべてのページに読み込む共通の css と特定のビュー hello/index.html.erb にのみ読み込む css を作成します。

- css/application.scss: すべてのページに読み込む共通の css。

- css/style.css: css/application.scss に読み込まれます。

- css/hello.css: 特定のビュー hello/index.html.erb にのみ読み込む css。

css/application.scss

@import 'style';

css/style.css

h1 {
    color: red;
}

css/hello.css

p {
    color: red;
}

画像について、images ディレクトリ配下に配置します。

ファイル構造は、以下のとおりです。

ファイル構造

app/javascript
  /css
    /application.scss
    /hello.css
    /style.css
  /images
    /noknow_logo.png
  /js
    /application.js
    /hello.js
    /hello_world.js
  /packs
    /application.js
    /hello.js

ビューの設定

デフォルトのレイアウトは、 views/layouts/application.html.erb になります。

このファイルにすべてのページに読み込ませるための JS, CSS を設定します。

views/layouts/application.html.erb

...
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
...

また、hello/index ビューに このページのみ読み込むための js, css と画像を読むこむように設定します。

views/hello/index.html.erb

<%= javascript_pack_tag 'hello', 'data-turbolinks-track': 'reload' %>
<h1>Hello#index</h1>
<p>Find me in app/views/hello/index.html.erb</p>
<%= image_pack_tag 'noknow_logo.png' %>

関連記事