skip to content
私的歌詞倉庫

Webpackerからvite_railsに移行した時に詰まったこと

/ 9 min read

Updated:
Table of Contents

はじめに

🎅GMOペパボエンジニア Advent Calendar 2023の23日目です。22日目はkenchanでした。

https://adventar.org/calendars/8634/embed

今回は業務で、Ruby on Rails + Vue.js(2.7)のプロジェクトで使っていたWebpackervite_railsに移行した話についてします。

Webpackerからvite_railsへ移行した動機としては以下の通りです。

  • Vue3アップデートのため
  • ビルドが結構時間かかるよね…とチーム内で話していた
  • Vue.jsならviteがデファクトスタンダードっぽい(社内でもviteの採用事例があった)

vite_railsではなくviteにするというのもありだったのですが、いきなりは大変そうだったので、一旦vite_railsに移行しました。

移行時に詰まったこと

移行手順に関しては、こちらの記事が非常に参考になりました。今回は自分が対応したときに苦労した点を中心に説明します。

Vue2関連のプラグインを追加

使っているVue.jsとVuetifyのバージョンが2系だったのでこちらのプラグインを入れました。

npm install -D @vitejs/plugin-vue2
npm install -D unplugin-vue-components

Vue.jsが2系なので@vitejs/plugin-vue2をインストールしています。

Vuetifyも2系なのでunplugin-vue-components/resolversをインストールしています。Vuetifyが3になったらVuetify公式のvite-plugin-vuetifyに移行しようと思っています。

設定はこのようにしました。

import { defineConfig } from "vite";
import RubyPlugin from "vite-plugin-ruby";
import vue from "@vitejs/plugin-vue2";
import { VuetifyResolver } from "unplugin-vue-components/resolvers";
import Components from "unplugin-vue-components/vite";
export default defineConfig({
plugins: [
RubyPlugin(),
vue(),
Components({
resolvers: [VuetifyResolver()],
}),
// 以下略…

resolverを使うことでいちいちimportしなくても、Vuetifyのコンポーネントを参照できるみたいなので設定しました(元々のプロジェクトがimport不要だったので対応)。

importのalias設定

元々Vue.js内で、import Hoge from "@components/Hoge" のように書いていました。これと同じ書きっぷりにするようにしました。

export default defineConfig({
resolve: {
alias: [
{ find: "@components", replacement: "app/javascript/components" },
{ find: "@lib", replacement: "app/javascript/lib" },
],
},
});

ただ注意が必要で、拡張子をつける必要があります。

import Hoge from "@components/Hoge";
import Hoge from "@components/Hoge.vue";
import fuga from "@lib/fuga";
import fuga from "@lib/fuga.js";

こんな感じです。本当はいい感じにシェルスクリプトなどで一括置換したかったのですが、数もそんなに多くなかったので、手でひたすら拡張子を追加しました。

requireをimportに置換

Viteではrequireが使えません。そのため、画像ファイルをdataで直接requireしていた箇所を、トップでimportしてからdata内で渡すように変更しました。

import image from "images/image.svg";
// 色々コードがあり…
data: function () {
return {
image: require("images/image.svg")
image: image
}
}

requireが使えないことを知らず、かなり時間を溶かしました…

グローバルSASSの設定

グローバルで使うSCSSがあったので、それをSASS内(今回はVue.js内のstyleをSASSで書いています)で自動で読み込めるように設定しました。

ポイントは改行を入れているところです。SASSは改行で1文と見なすのでjoinで改行コードを入れています(参考にしたIssueがあったのですが見失いました…)。

export default defineConfig({
css: {
preprocessorOptions: {
sass: {
additionalData: ["@import 'hoge/fuga.scss'", ""].join("\n"),
}
}
}
}

タグヘルパーの変更とfavicon

webpackerからvite_railsに移行したのでvite_railsのタグヘルパーに置き換えます。そんなに難しくなかったです。

(プロジェクトがhamlなのでhamlで書いています)

= javascript_pack_tag 'hoge'
= vite_javascript_tag 'hoge'
= image_pack_tag 'media/images/hoge.svg'
= vite_image_tag 'images/hoge.svg'

画像ファイルは読み込むディレクトリが変わるので注意が必要です。こちらを参考にすると良さそうです。

次にfaviconです。もともとfaviconをpublicディレクトリに置いていました。publicは毎回vite_railsが消してる?っぽくいつの間にかfaviconが消えていたので保存するディレクトリを変更しました。

最初は、javascript/images に置いていたのですが、いい感じに読み取れませんでした。どうやらheadタグ内では、タイミング的にうまくjavascript/images から読み込めない(manifest.jsonが作られてない?)ような感じでした(要調査)。そのため、javascript/entrypoints にfaviconを置くようにしました。

%html(lang='ja')
%head
%link{rel: 'shortcut icon', href: '/favicon.ico', type: 'image/x-icon'}
%link{rel: 'shortcut icon', href: vite_asset_path('favicon.ico'), type: 'image/x-icon'}

開発中にvue-devtoolsを有効化

Vue.jsの開発ではデバッグツールとしてvue-devtoolsというブラウザ拡張機能があります。Webpackerのときは特に設定もなくブラウザに拡張機能さえ追加すれば、開発中は自動で有効になっていた気がしますが、vite_railsになってから無効になっていました。そのため、設定をコード上で有効にしました。

if (import.meta.env.MODE === "development") {
Vue.config.devtools = true;
}

import.meta.env.MODE はviteが勝手に追加する環境変数でここに今開発中かどうかが入っています。他にも予め設定されている環境変数があり、詳細は公式サイトにあります。

上記の設定でVue2.7は動いていたのですがVue3になってからは動かなくなっていました。その話を↓で書いています。

Vite + Vueで開発中に強制的にVue Devtoolsを表示

移行した結果

Webpacker(5.4.4)時代の速度は正確に計測していないのですが、ローカル環境を立ち上げるときは、色々込みで大体8~10分程度だったと思います。それがvite_rails(3.0.17)に移行してからは約2分程度になり、かなり速度向上に繋がりました。

終わりに

Webpackerをvite_railsに移行した話をしました。今のところvite_railsに移行して困ったことはないのでやってよかったなと思います。やはり開発環境での速度向上が一番嬉しかったです。

明日のアドベントカレンダーはugoくんです。

参考文献