1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Webpackerからjsbundling-rails + esbuildに移行してReactを動かした話(Rails7.0→7.1アップデート)

Posted at

背景

読んで欲しい人

  • 同じような場面に直面した人
  • 過去のなーんにもわかってない俺

環境について

  • Rails 7.0.8
  • Ruby 3.2.2
  • Webpacker 5.4.4
  • sprockets 4.2.1
  • React 16.0.

簡単に用語の整理

Sprockets

  • app/assets配下にある、js,css,画像などのアセット群を1つにまとめてくれる。Rails6より前でディフォルトだったぽい。Webpackerとは役割が被っている

webpackerとは

  • Rails6.0より標準搭載となったWebpackを使用したjs,css,画像などのアセット群を1つにまとめてくれるモジュールバンドラーです。Rails7.0以降には推奨されなくなり、現在では開発もストップしています。
  • Webpackとは?
    • 複数のjsファイルを1つにまとめてくれるモジュールバンドラーです。node.jsのモジュールの1つ
    • js以外のcssや画像ファイルもまとめてくれるが、ややこしくなるのでこの記事ではjs以外はスルーします。
  • node.jsとは
  • モジュールバンドラーとは
    • 複数のJSファイルの依存関係を勝手に解析して、いい感じに1つのファイルにまとめてくれる機能があるやつ

jsbundling-railsとは

  • Railsとjsバンドラーの連携をいい感じにしてくれる「ブリッジツール」的なもの
  • ビルドしてくれた後のファイルを適切な場所に置いてくれる
  • バンドラーが初期設定を行なってくれる

esbuild

  • jsのバンドラー
  • jsのバンドルを比較的高速に行ってくれるらしい

jsbundling-railsとesbuild(別のバンドラーでも良いが)の2つが揃って連携して初めて、Webpackerの代わりとして機能します

乗り換え

jsbundlig-rails

  • gemfileにgem 'jsbundling-rails'を追記

esbuild追加

  • esbuildのインストール
$ ./bin/rails javascript:install:esbuild

そうすると下記のファイル生成、変更が行われる

  • .gitignoreファイルの更新
  • foremanで複数のプロセスを実行するためのProcfile.devファイルの生成
  • app/assets/buildsディレクトリ→この時点では.keepファイルだけ
  • manifest.jsの更新
  • app/javascript/application.jsのエントリーポイントファイル生成
  • javascriptのインクルードタグ追記
  • bin/devスクリプトファイル生成
  • pakage.jsonの更新

生成されたファイルをざっくり説明

  • Procfile.devファイル
    • Procfile.devに書かれた複数のプロセスをforeman startコマンド1つで一度に立ち上げてくれます
Procfile.dev
# Railsサーバーの立ち上げ
web: bin/rails server
# バンドラーの実行(後述)
js: yarn build --watch
  • bin/devスクリプトファイル
    • bin/devとターミナルに打ち込むとforeman startを実行してくれるファイル
# bin/dev

#!/usr/bin/env bash

# foremanがインストールされていなければインストール
if ! command -v foreman &> /dev/null
  then
    echo "Installing foreman..."
    gem install foreman
fi

# Procfile.devを元にforemanを起動
foreman start -f Procfile.dev "$@"
  • app/assets/buildsディレクトリ

    • esbuildでビルドした後のファイルをここで管理してくれる
    • この時点では.keepファイルだけ
  • pakage.jsonのscript

    • 下記のようなコマンドが追加されている
package.json
  "scripts": {
    "build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets"
  }
  • app/javascript/application.jsのエントリーポイントファイル
    • esbuildのエントリーポイント。Webpackerでいうところのapp/javascript/packs/application.jsにあたる

jsの移行

  • Sprocketsを利用している
  • esbuildでcssファイルもビルドしたい

みたいな場合はapp/javascript/application.jsのエントリーポイントファイル名を、app/javascript/esbuild_application.js(任意の名前)にしてください。詳しくは「詰まった箇所」で後述しますが、既存のSprocketsの生成したcssファイルと名前がかぶるのでSprockets::DoubleLinkErrorsが出てはまります

  • ReactをWepackerのエントリーポイントからesbuildのエントリーポイントに移動させます
app/javascript/packs/application.js

  require("controllers")
  require("@rails/ujs").start();

  import React from 'react';
  import { render } from 'react-dom';
  
  // Reactで使用していたcss 後述
  import 'slick-carousel/slick/slick.css';
  import "slick-carousel/slick/slick-theme.css";
  import 'slick-carousel/slick/slick-theme.css';

  // Reactのコンポーネントimport
  import Slide from './components/Slide';
  import PresentationEditor from './components/PresentationEditor';
app/javascript/application.js または esbuild_application.js

import "./controllers"
import Rails from @rails/ujsRails.starts()

import React from 'react';
import { render } from 'react-dom';

// Reactで使用していたcss
import 'slick-carousel/slick/slick.css';
import "slick-carousel/slick/slick-theme.css";
import 'slick-carousel/slick/slick-theme.css';

// Reactのコンポーネントimport
import Slide from './components/Slide';
import PresentationEditor from './components/PresentationEditor';

app/javascript/packs/application.jsでrequireを使用している部分はimportに変更してください

webpackerで使用しているtagを削除する

  • webpackerで使用していたjavascript_pack_tagなどをここでjavascript_include_tagに差し替えます

  • esbuildでcssもビルドしている場合はstylesheet_link_tagを利用してください。sprocketsを利用している場合はesbuildで読み込むためのstylesheet_link_tagも必要になります

application.html.erb
  <%= stylesheet_link_tag 'esbuild_application' %>

  <%= javascript_pack_tag 'application' %>

  <%= javascript_include_tag "application", defer: true %>
    or
  <%= javascript_include_tag "esbuild_application", defer: true %>

Webpacker掃除

  • Webpacker関連のファイルやライブラリなどを削除します
    • gemfileからの削除
    • ./bin/webpack
    • ./bin/webpack-dev-server
    • ./config/initializers/webpacker.rb
    • ./config/webpacker.yml
    • ./config/webpack/development.js
    • ./config/webpack/environment.js
    • ./config/webpack/production.js
    • ./config/webpack/test.js

package.josnのscriptを修正

  • pakage.jsonのscriptでReactの拡張子を認識させる
    • scriptに--loader:.js=jsxオプションを入れます。jsxファイルをインポートして、依存関係に含めます。そしていい感じにコンパルしてくれます
package.json
  "scripts": {
    "build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --loader:.js=jsx
  }

詰まったこと

  • 詰まった箇所: Reactで使用しているcssファイル

      import 'slick-carousel/slick/slick.css';
      import "slick-carousel/slick/slick-theme.css";
      import 'slick-carousel/slick/slick-theme.css';
    
    • ReactのSlick内で使用されているCSSの設定方法で詰まった。
      • CSSだけSprocketsに移動しようとしたができなかったです。原因はいまだに不明
      • cssbundling-railsを利用してcssをビルドしようとしたが、できなかった。原因はすでにesbuildで生成されていることを知らなかったから(esbuild_application.jsからの消し忘れで気づけた)
      • Sprocketsのcssファイル名と競合してSprockets::DoubleLinkErrorsエラーになってしまった。原因はどちらも最終的にはapplication.cssファイルとして読み込まれるので同じファイルが2つあると認識されていた。esbuildで生成されたcssファイルについてはesbuild_application.cssとしてファイル名を変更して解決

感想

  • そもそもRailsのフロント周りは移り変わりが激しく色々な単語が登場するのでとても苦戦しました
  • 「Webpacker剥がし」なるものを実際に1人で経験できて前よりもフロントへの解像度が増えてよかったです

参考にした記事

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?