RareJob Tech Blog

レアジョブテクノロジーズのエンジニア・デザイナーによる技術ブログです

ビルドツールをLaravel MixからViteに移行

こんにちはフロントエンドグループの大谷です。

自宅の備え付けのエアコンが古く、スイッチを入れてから10分くらい起動しなくて困っています。 猛暑日が続いているので起動は高速であってほしいものですね。。

プロダクト開発においても、歴史を重ねるとビルド速度が遅くなることがありますね。 今回はそんな課題を抱えていたリポジトリに、速いと評判のViteを導入した話について書いていきたいと思います。

Viteとは何か

Vue.jsの開発者でもあるEvan You氏が開発したビルドツールです。

  • VueやReact等多くのフレームワークをサポートしている
  • Laravel 9以降はLaravel Mix→Viteが標準
  • バンドル不要で開発サーバーの起動が早い
  • HMRが修正分のみを適応するため、モジュールの総数に関係なくかなり高速

(引用:https://ja.vitejs.dev/guide/why.html )

どんなことをやったのか

課題になっていたこと

今回対象となったリポジトリでは一部の機能がVueで作られています。SCSSファイルとVue・jsファイルがLaravel Mixでのビルド対象となっています。 このリポジトリではビルドの工程がCIにのせられておらず、ローカルでのビルドが必要になっています。

管理している範囲が広く、また歴史のあるシステムのため下記のようにファイル数が肥大化している状況でした。

SCSSファイル数 ビルドツール Nodeバージョン 構成
343 Laravel Mix5系 v12.22.1 MPA

Vue3のアップデートも計画しているためNode16以上へのアップデートが必要があり、前段の作業としてNodeのバージョンを作業実施時にlatestだったv18.16.0に更新したところ元々時間がかかっていたVueとSCSSのトランスパイルに要する時間が更に長くなる結果となっていました。

Laravel Mix5系:Vue + SCSSのを対象にした場合(productionモード)

Node12 + node-sass + Vue Node18 + Dart sass + Vue
ビルド時間 1分48秒 8分56秒

Laravel Mix5系:Vue + SCSSのを対象にした場合(developmentモード)

Node12 + node-sass + Vue Node18 + Dart sass + Vue
ビルド時間 1分44秒 1分42秒

Laravel Mix5系:対象をVueに絞った場合

Node12 + Vue Node18 + Vue
ビルド時間 6.916秒 3.802秒

Vue単体ではそこまで時間がかかっていないので、SCSSのトランスパイルがボトルネックになっているようでした。 このままでは流石に開発効率に影響する速度です。。

対応したこと

対応の選択肢としては下記がありましたが

  • Laravel Mix5→6系に更新しwebpackの設定をチューニングする
  • Viteに変更する

Laravelを利用したプロジェクトも多数あるため、Laravel Mix→Viteへの移行の検証を行いたいという理由でLaravel MixからViteへの変更を行いました。

laravel-vite-pluginも提供されていますが、今回対象になっているリポジトリではyii frameworkで構成されているため利用を見送りました。

結果どうなったか?

productionビルドで約6秒と大幅な改善が見られました。

Vite:Node18

Dart sass + Vue Vue
ビルド時間 5.59秒 2.43秒

なぜこの結果になったのか?

  • 複数ファイルから参照されるモジュールは個別のESmodulesとして出力される
    上がLaravel Mixで下がViteの結果です。
    グレーアウトしている部分が多いのでわかりづらいのですが、Vueの依存関係がViteの場合別ファイルにまとまっていることがわかります。

  • CSS圧縮は組み込みサポートされていて、esbuild、terserを選択可能(デフォルトはesbuild。今回は検証不足のためterserを選択)
  • SCSSのトランスパイルについては内部的にsass-loaderを使っているようなので、差分はそれほどなさそう

productionビルドに関してはここまで結果の差が出るとは思っていませんでした。
ビルドに要する時間のみを見ると、SCSS圧縮の部分で大きな改善が見られたので今回の場合Laravel Mixのままでもその部分を見直せば改善できた可能性もあったのかもしれません。

はまりどころ

  • SCSS

元々のディレクトリ構成が複雑なので、トランスパイルしたcssを出力するディレクトリ構成の保持がデフォルト設定では困難でした。提供されている変数では解消できなかったため、Viteの設定ファイルで制御するようにしました。(そもそもトランスパイル後のcssは複雑なディレクトリ構成にしない方が良さそう)

  • Vue・js

    • 出力結果がESmodulesを採用しているため、jsファイルの読み込み方の変更が必要

      ASIS:<script type="text/javascript" src="/js/xxx.js"></script>
      TOBE:<script type="module" src="/js/xxx.js"></script>

      古いブラウザではサポートされていないので注意が必要です。 レガシーブラウザもプラグインでサポート可能ですが、今回の対象ページではサポート外のブラウザの利用率0.13%だったのでレガシー対応はせずに利用しています。

    • ランタイムオンリービルドがデフォルト設定なので完全ビルドの場合はaliasの設定が必要 bladeからpropsをわたしているケースで思うようにVueテンプレートに値がわたっていなかったのですが、Laravel Mixの場合はaliasの設定は不要で、意識せずに解決されていた部分だったのでパッとわからずはまってしまいました。(おそらく依存関係にvue-loaderが含まれていたので意識せず解決してくれてた可能性が高い)


      (引用: インストール — Vue.js )

    • require()が使えない ViteはESmodulesによって動作しているので、requireは変換されない。requireはCommonJSの仕様でブラウザでは読むことができないのでエラーとなります。 そのため今までrequireで読み込んでいた部分はimportへの書き換えが必要になります。

まとめ

  • ビルドが爆速に
  • cssをgit管理しているが故の手順が一つ削減
    • トランスパイル後のcssをgit管理しているためlocalでの ビルドが必須だが、重すぎて以前は開発中とpush前でビルドの実行コマンドを分けていたが、分ける必要がなくなった(今回の主題からはずれてしまうため記載していませんが、CIも整えたい)
  • Vue3のアップデート対応の準備ができた

上記の内容が改善され、開発効率はとても良くなりました。
部分的にはまりどこともありましたが、今回の場合対象がほぼSCSSでVueファイルの対象が少なかったため移行も比較的簡易に行うことができました。
対象範囲が広い場合は、requireの解消などエラーの解消のために変更が必要になる部分も多く、またファイル分割数など異なる部分も多数あるので充分に検証を行う期間を確保する必要がでてくると感じました。

今回使うことができませんでしたが、開発サーバーを活用した機能は開発体験をさらに良くしてくれそうなので HMRの活用(開発サーバーの起動だけためしたところ700msほどだった)についても今後検討していければと思います。