カタベログ

IT技術に関するブログを書きたい.食べ物関連はInstagramをご参照の事.

ViteをVue2のプロジェクトに入れてみた

背景

2021年末、関係者たちが次々冬休みに入る中、年長者なのでしんがりを買って出た。 一部コミュニケーションのミスもあったりで、結果としては1日2日多く休めたはずだった。 打ち合わせもなければメンバからの相談事もPRレビューもなく、かといって面倒臭い仕事もやる気もしない。 そんな気分の折、メンバの一人がTypeScriptでツールを作成していたことに触発されて、1日つかって新しい技術を組み込んでみようと思い立ったのであった。

モチベーション

  • ローカルビルドやHMRの時間を短縮して開発効率を上げる
    • Vue2のままViteを導入する
    • テストがないのでVite関連では極力コードに手を入れない

ちなみにViteが何かは日本語ドキュメントもあるので以下をチェック。

ja.vitejs.dev

やり方

ざっくり以下の通り。

  1. vue-cli-plugin-viteをインストールする
    1. パッケージのREADMEにあるUsageの通りに実施
  2. @でパスを記載しているところを相対パスに直す
  3. main.jsみたいなエントリーポイントにマウントするための処理が書いているJSをsrc直下に移動
  4. 環境変数の読み込みをprocess.envからimport.meta.envに直す
    1. ただし、単純な書き換えだけしてしまうとvue-cliによる本番ビルドが失敗する
    2. string-replace-loaderを使ってvue-cliによる本番ビルド時のみprocess.envに置換するようにする
  5. 環境変数の名前をVUE_APP_****からVITE_****に直す
  6. Common JSで作成したモジュールをES Module形式に書き直す
    1. vue-cliでは問題ないが、Viteではこのままだとエラーになってビルドできない
  7. vue.config.jsプラグインのREADMEに基づいて設定を行う
    1. TypeScriptを使っていなかったのでタイプチェックを無効にした
    2. 加えて、Lintはhuskyでコミット毎に行っているのでこれも無効にした
  8. VSCodeでveturを使っているなら、vetur.experimental.templateInterpolationServiceを無効にする

詰まったところ

引っ掛かるべきところにはすべてひっかかった感ある。

ただのViteは入れられない

最初にこちらの記事を参考に始めた。

バージョン情報

Vue 3.2.20(※Vue2でも基本的に同じ方法で移行できますが検証は行っていません🙏)

vite: 2.6.14

結果として私が検証したことになったのだが、結論、移行できないみたいでした。

yarn run v1.22.17
warning ../../../../package.json: No license field
$ vite serve
error when starting dev server:
Error: Failed to resolve vue/compiler-sfc.
@vitejs/plugin-vue requires vue (>=3.2.13) or @vue/compiler-sfc to be present in the dependency tree.

なので、諦めて再度情報収拾をしなおし、vue-cli-plugin-viteならイケると分かったので方向転換しました。

node_modulesの外から組み込んでるライブラリが読み込めない

以下のエラーに遭遇。

$ node ./bin/vite
running: vite --config /Users/username/project-name/node_modules/vue-cli-plugin-vite/config/index.ts
error when starting dev server:
Error: The following dependencies are imported but could not be resolved:

ビルド時にnode_modulesの外から呼ぶライブラリ、例えばテンプレートにてscriptタグで読み込んでるものはそのままではビルドできない。 optimizeDeps.includeをするとうまくいくなんてあったが、自分は指定の仕方が悪いのかうまくいかなかった。 そもそもとして、別にnode_modulesの外から呼ぶ必要性もなさそうだったので、node_modulesに取り込んで問題を回避した。

veturとの連携によってエラーやらサジェスチョンやら出る

テンプレート内型チェックだったり、node_modulesのライブラリで型定義がないものがあるとエラーなりサジェスチョンなりしてくれるみたい。 TypeScriptは導入していないのでありがた迷惑であったことから、それぞれ以下のように対応した。

  • vue-cli-plugin-vite
    • disabledTypeCheckerをture
  • vetur
    • vetur.experimental.templateInterpolationServiceをfalse

なお、筆者はVSCodeで開発してて、veturってのはVue2向けのVSCodeプラグインです。

pluginの仕組み上、生成されるコンフィグがviteの全てのコンフィグを使えるようになっていない

パッケージのREADMEにあるオプションしか対応していない。 rootとかいじりたくてもいじれないので、やむなくmain.jsみたいなエントリーポイントにマウントするための処理が書いているJSをsrc直下に移動させた。

モジュールは全てES Module(ESM)にしないと動かない

ビルドが通ったので開発者ツール起動しながら動かしてみていたが、コンソールにエラーとして〜.jsからそんな名前のものはエクスポートされてないよ!ってエラーが出ていた。 どうやらモジュールは全てES Module(ESM)にしないといけないようだった。特に問題はないので、module.exports/requireとかを使うCommon JSの書き方からexport/importのESMの書き方に直した。

本番ビルドにVue2向けプラグインは対応していない

vue-cli-plugin-viteはIssueにFAQがあり、そこに書いてあった。 仕組み自体は簡単そうなので、もしやる気がある人はForkしてPRしてみるといいかと。

環境変数読み込みの違いのせいでvue-cliによるビルドが失敗する

てなわけで、本番ビルドは引き続きvue-cliを使うことにした。 となると、環境変数の名がローカルと本番では異なることになってします。 どうやら、process.env.VITEの有無でViteを使ってビルドしているかがわかるようだったので、環境変数の値によって読み込む環境変数名を変えるようコードを修正した。 ただ、2系のvue-cliが使っているwebpack(lockを見ると4系)だとimport.meta自体が解釈できずビルドエラーになった。 import.metaって表記をwebpackでビルドする前に解消できるようにする方法として、力技ではあるが問題ないので string-replace-loaderを使ってprocessに置換するようにした。

結果として早くなったのか?

ここまでの対応をすべて行うと、ローカルビルドは自分の環境はで12〜15秒、HMRは瞬殺でした。