
vite_railsで複数のエントリーポイントをビルドする
以下のようにjsやcssをなんらかの単位で分けてビルドしたい場合、railsの通常のビルドの設定ではなくvite_railsを使うと便利。
entrypoints
にはvite_railsでビルドするターゲットファイルを設置。ターゲットファイルから他のディレクトリにある資材を読み込むことになる。
frontend
|-- entrypoints < buildの対象を配置
|-- main < エンドユーザー向けの資材
|-- admin < 管理画面用の資材
|-- lp < 広告配信用の資材
vite_railsのインストール
まず、デフォルトのビルド設定を省きたいので、--skip-javascript
を設定してrails newする。
$ rails new . --skip-javascript
自分の場合、他にも取り除きたいものがあったので、こんな感じで実行。それぞれ必要になったら、後から足せばOK
rails new . --skip-action-mailbox --skip-javascript --skip-jbuilder --skip-brakeman --skip-rubocop --skip-ci --skip-kamal --skip-test --skip-system-test --skip-thruster
そしたらvite_railsをインストール。そしてviteの設定ファイルを生成。
$ bundle add vite_rails
$ bundle exec vite install
そうすると、config/vite.json
とvite.config.ts
、package.json
ができる。ビルド関連で必要なものや設定があればさらにここへ追加すればOK。
{
"all": {
"sourceCodeDir": "app/frontend",
"watchAdditionalPaths": []
},
"development": {
"autoBuild": true,
"publicOutputDir": "vite-dev",
"port": 3036
},
"test": {
"autoBuild": true,
"publicOutputDir": "vite-test",
"port": 3037
}
}
import { defineConfig } from 'vite'
import RubyPlugin from 'vite-plugin-ruby'
export default defineConfig({
plugins: [
RubyPlugin(),
],
})
{
"private": true,
"type": "module",
"devDependencies": {
"vite": "^5.4.14",
"vite-plugin-ruby": "^5.1.1"
}
}
npm installをしてnodeのモジュールをインストールしておく
$ npm install
このままbin/dev
をしてもrailsのサーバーのみが立ち上がるだけで、viteのホットリロードなどが動作しない。
そこで、foremanを使ってbin/devを実行したときにrailsサーバーとviteが同時に立ち上がるように変えていく。
$ bundle add foreman --group development # これは開発環境のみインストールされていればOK
foremanが読み込むProcfile.dev
はすでにviteとrailsが同時に走るようになっているので、そのままでOK
vite: bin/vite dev
web: bin/rails s
bin/dev
の中身をforemanを実行するように変更。これでbin/devを実行すると、http://localhost:5100でrailsの最初の画面が表示され、背後でviteも動いているようになる。
# 変更前
#!/usr/bin/env ruby
exec "./bin/rails", "server", *ARGV
# 変更後
#!/usr/bin/env sh
bundle exec foreman start -f Procfile.dev
ただ、5100のポートって普段からrails使っている人だとちょっと慣れない。
おなじみの3000を使いたいときは、以下のような感じでProcfile.dev
のrailsのところを書き換えてあげると3000で起動するようになる。
vite: bin/vite dev
web: unset PORT && bin/rails s
資材の配置
あとは、最初に書いた構成でapp/frontend
配下にディレクトリを作り、jsとかcss、画像を配置すればviteが自動でbuildをしてくれる。
ただ、画像についてはfrontend直下のimagesしかデフォルトでは読み込んでくれない。それぞれのエントリーポイントごとに画像も別で管理したい場合は以下のようにconfig/vite.json
で読み込み対象として追加してあげる。
{
"all": {
"sourceCodeDir": "app/frontend",
"watchAdditionalPaths": [],
"additionalEntrypoints": [
"~/main/images/**/*",
"~/admin/images/**/*",
"~/lp/images/**/*"
]
},
"development": {
"autoBuild": true,
"publicOutputDir": "vite-dev",
"port": 3036
},
"test": {
"autoBuild": true,
"publicOutputDir": "vite-test",
"port": 3037
}
}
あとは、layouts/application.html.erb
あたりでapp/frontend/entrypoints
に配置した資材を読み込むように指定してあげればOK。
おそらくこの構成取りたい場合はlayoutsもそれぞれentrypointsごとに用意することになると思うので、適宜作成しておきましょう。
<!DOCTYPE html>
<html>
<head>
<title><%= content_for(:title) || "Nice project" %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= yield :head %>
<link rel="icon" href="/icon.png" type="image/png">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/icon.png">
<!-- 以下3点を追加 -->
<%= vite_stylesheet_tag 'main.css' %>
<%= vite_client_tag %>
<%= vite_javascript_tag 'main' %>
</head>
<body>
<%= yield %>
</body>
</html>
画像を読み込むときは以下のような感じでvite用のヘルパーを使用する。
他にも資材の読み込み方については、こちらに詳細があります。
<%= vite_image_tag 'main/images/cat.png' %>
HotwireとStimulusを有効にする
rails newしたときに--skip-javascript
をしたので、HotwireとStimulusが入っていません。
改めてセットアップするにはturbo-railsとstimulus-railsのgemをインストールして、セットアップコマンドを実行
$ bundle add turbo-rails stimulus-rails
$ bin/rails turbo:install
$ bin/rails stimulus:install
インストールは完了するんだけど、残念なことにyarnでインストールされてしない、yarn.lock
ができてしまった。
もともとyarnを使うつもりなら問題ないけど、npmを使いたい場合は一旦yarn.lock
を削除して、npm installを実行しておこう
$ rm yarn.lock
$ npm install
そして、Turbo(Hotwire)とStimulusをインストールしたときに、デフォルトのテンプレートがapp/javascript
に作られているのだけどviteを使う場合app/frontend
に資材を配置しないといけない。
紛らわしいので、一旦app/javascript
は削除してstimulus-vite-helpersのインストールしておく。stimulus-vite-helpersはvite上でstimulusのcontrollerを効率よく読み込むためのヘルパーを提供してくれる。
$ rm -rf app/javascript
$ npm install stimulus-vite-helpers
エントリーポイントの対象となるファイルに以下のような設定をしてあげればOK。
あとは/main/js/controllers/
配下にいつものようにStimulusのコードを配置しておけばvite上で稼働します。
import "@hotwired/turbo-rails"
import { Application } from '@hotwired/stimulus'
import { registerControllers } from 'stimulus-vite-helpers'
const application = Application.start()
const controllers = import.meta.glob('../main/js/controllers/*_controller.js', { eager: true })
registerControllers(application, controllers)
ある程度規模の大きいサイトやサービスになると、複数の想定ユーザーごとにフロントエンドが必要になるケースはよくありうると思う。
そうしたときに、vite_railsを使うと綺麗に分けやすいですよ、という話でした。Sassも使えるようになります。
バージョン情報
- rails 8.0.1
- vite_rails 3.0.19