Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8960

【Vue 2.x】Vue CLI環境にViteを導入して開発ビルドを爆速にする

$
0
0

2021/02 に Vite 2.0 正式版がリリースされ、開発サーバーの起動や HMR (Hot Module Replacement) の動作が軽快なフロントエンド開発環境を手軽に構築できるようになってきました。

これとほぼ同時期に、既存の Vue 2.x + Vue CLI環境に Vite 環境を同居させ、開発ビルドにだけ Vite を活用する vue-cli-plugin-viteがリリースされました。このプラグインは「コードベースの変更なしに」を謳っていて、Vue CLI 向けの設定ファイル vue.config.jsを Vite 向けの設定に変換1することで Vite 開発サーバーを起動させる機能を持っています。
実際に Vue CLI 環境へ導入してみたところ、「コードベースの変更なしに」は概ね正しかったものの vue.config.jsなどに修正が必要でした。

設定に若干難しさはあったものの、開発サーバーの起動時間が 3 秒程度になって HMR の動作も大幅に改善されました
本記事では、設定ファイルの修正方法や Vite 開発サーバーにおける注意点などを共有します。

image.png

動作確認環境

  • macOS Catalina
  • Chrome 89
  • Node.js 14
  • npm 6
  • Vue CLI v4.5.11
    • vue 2.6.12
    • vue-cli-plugin-vite 0.3.2
    • typescript 3.9.9
    • sass (dart-sass) 1.32.8
    • sass-loader 8.0.2

プラグインの導入

Vue 2.x + Vue CLI 環境のディレクトリ上で vue add viteまたは npx @vue/cli add viteを実行してプラグインを導入します。

プラグインを導入すると、package.jsonnpm run viteのタスクが追加され、 bin/viteというシェバン付きの JavaScript ファイルが作成されます。

package.json
{"scripts":{"serve":"vue-cli-service serve","build":"vue-cli-service build","lint":"vue-cli-service lint","vite":"node ./bin/vite"}}

各種設定

開発サーバー立ち上げ時にブラウザを起動しないようにする設定

環境変数 BROWSER=noneをセットします:

package.json
{"scripts":{"serve":"vue-cli-service serve","build":"vue-cli-service build","lint":"vue-cli-service lint","vite":"BROWSER=none node ./bin/vite"}}

テンプレート上での空白の取り扱いの設定

Vue CLI 環境では whitespaceのデフォルト設定が condenseでしたが、Vite 環境では preserveになっていました。

condensepreserve
condenseでのレンダリング結果preserveでのレンダリング結果

この違いによって、ブラウザ上での余白の表示が変化することもあるため、Vite 開発環境においても whitespacecondenseにする設定を追加します:

vue.config.js
module.exports={pluginOptions:{vite:{vitePluginVue2Options:{vueTemplateOptions:{compilerOptions:{whitespace:'condense',},},},},},};

ネストが深くなっていてわかりにくいですが、各種オプション名は以下ような対応となっています:

  • vite: vue-cli-plugin-viteの設定
  • vitePluginVue2Options: vite-plugin-vue2の設定
  • vueTemplateOptions: @vue/component-compiler-utilsの設定
  • compilerOptions: vue-template-compilerの設定

<style lang="scss">ブロックへのコードの自動挿入設定

Vue CLI 環境には .vueファイルの <style lang="scss">ブロック2変数等を自動挿入する設定があります。
これを Vite 環境でも利用するには、vue.config.jsを以下のように設定します:

  • css.loaderOptions.sassで設定している場合は css.loaderOptions.scssに変更する
  • sass-loader v8 の場合、Vue CLI 環境では css.loaderOptions.scss.prependDataとして振る舞い、 Vite 環境では css.loaderOptions.scss.additionalDataとして振る舞うように設定する3
vue.config.js
// Vite 開発環境であるかを判定するための変数を用意する。// ここでは「開発サーバー立ち上げ時にブラウザを起動しないようにする」の設定した上で、その設定の有無にて判定します。constIS_VITE_ENV='BROWSER'inprocess.env;module.exports={css:{loaderOptions:{scss:{[IS_VITE_ENV?'additionalData':'prependData']:`
          $main-color: #123456;
        `,},},},};

バンドル結果を別のサーバーで配信している環境の場合

Vue CLI 環境の開発ビルド(npm run serve)でディスク書き込みを有効にして、バンドル結果の js ファイルや css ファイルを別のサーバー環境で配信している場合もあるかと思います。
この場合は Vite 開発サーバー起動と同時に、Vite 開発サーバーが配信するモジュールを読み込むためのコードをディスクに書き込む必要があります。

ここでは以下の状況を仮定します:

  • src/main.tsがエントリーポイント
    • 出力先は dist/app.js
  • npm run serve時のディスク書き込みが有効
  • Vue CLI / Vite 開発サーバーのポート番号は 33333
  • http://localhost:8080/foo/bar/dist/の内容を配信している
  • localhost:8080側で配信する HTML に <script src="/foo/bar/app.js"></script>が埋め込まれている
vue.config.js
module.exports={configureWebpack:{output:{filename:'[name].js',},},devServer:{port:33333,writeToDisk:true,},publicPath:`/foo/bar/`,};

vue-cli-plugin-vitedevServer.writeToDiskまでは考慮しないので、dist/app.jsに Vite 開発サーバー側のモジュールを参照させるコードを書き込む必要があります。

dist/app.jsの書き込み

http://localhost:33333/foo/bar/src/mainを読み込むように設定します。

この dist/app.jsモジュールではなく通常のスクリプトであるため、import文ではなく動的 import()を利用します4:

dist/app.js
import('http://localhost:33333/foo/bar/src/main');

npm run vite実行時に上記内容を書き込むため、bin/viteに以下の内容を追記します:

bin/vite
// 以下をファイル下部に追記するconstfs=require('fs').promises;// const path = require('path'); は既に定義されているconstgetPath=pathSegment=>path.resolve(__dirname,'../',pathSegment);(async()=>{// dist ディレクトリがない場合は作成するawaitfs.mkdir(getPath('dist/')).catch(()=>{});// dist/app.js を書き込むawaitfs.writeFile(getPath('dist/app.js'),`import('http://localhost:33333/foo/bar/src/main');`).catch(e=>console.error(e));})();

画像ファイルの配信するためにシンボリックリンクを作成

.vueファイルのテンプレートに <img src="@/assets/logo.png">のように書くと <img src="/foo/bar/src/assets/logo.png">のような img タグがレンダリングされるため、http://localhost:33333/foo/bar/src/assets/logo.png
ではなく http://localhost:8080/foo/bar/src/assets/logo.pngを参照しようとしてしまいます。

記事投稿時点では適切な設定オプションが無かった5ため、やむを得ず dist/src/へのシンボリックリンクを作成して localhost:8080側で画像ファイルを配信します:

$cd dist/
$ln-s ../src/ src

npm run vite実行時に上記の操作をするため、 以下のコードを bin/viteawait fs.mkdir(...);の下に追記します:

awaitfs.symlink('../src/',getPath('dist/src')).catch(()=>{});

/から始まるパスの画像ファイルを読み込めるようにする

.vueファイルのテンプレートに <img src="/img/photo.jpg">のように書いて http://localhost:8080/img/photo.jpgを参照しようとすると、Vue CLI 環境では問題なくコンパイルできるものの Vite 開発環境では以下のようなコンパイルエラーが出てしまいます:

[vite] Internal server error: Failed to resolve import "/img/photo.jpg". Does the file exist?

vite-plugin-vue2の実装を追っていったところ、以下のようにして transformAssetUrlsOptions.forceRequireの設定を追加する必要がありました:

vue.config.js
module.exports={pluginOptions:{vite:{vitePluginVue2Options:{vueTemplateOptions:{compilerOptions:{whitespace:'condense',},transformAssetUrlsOptions:{forceRequire:false,},},},},},};

注意事項

ES モジュールを用いていること

Vite 開発サーバーはモジュールの利用を前提としています。
特に IE11 はモジュールに非対応のため、IE11 で動作確認するには従来通り Vue CLI 環境を用いてバンドルする必要があります。

型エラーやフォーマットエラーはターミナル上のログとして表示されない

Vite は TypeScript による型チェックや Linter によるフォーマットチェックを行いません。エディタでの保存時に自動でフォーマットをする設定や、CI でエラーを検知できる仕組みなどを導入しておく必要があるでしょう。

esbuild を利用している

esbuildをトランスパイラとして用いているため、OS と CPU アーキテクチャに依存するバイナリが node_modulesにインストールされます。
特に Docker や仮想マシンを利用している場合は、異なる OS 間で node_modulesディレクトリを共用できないことに注意が必要です。

$file node_modules/esbuild/bin/esbuild
node_modules/esbuild/bin/esbuild: Mach-O 64-bit executable x86_64

まとめ

Vue CLI 環境ではプロジェクトの規模が大きくなればなるほど開発ビルドが重くなり、開発体験が悪くなっていく傾向がありましたが、vue-cli-plugin-viteのおかげでこの問題を解決できました。
設定に若干難しさがありますが、本記事を参考に Vite 開発環境を試していただければ幸いです。


  1. どのオプションが変換の対象となるかについては README.mdを参照 

  2. scss + Scoped CSS (<style lang="scss" scoped>) や scss + CSS Modules (<style lang="scss" module>) も対象 

  3. sass-loader v7 の場合は css.loaderOptions.scss.data, v9 の場合は css.loaderOptions.scss.additionalDataを用います。v9 以降であれば三項演算子と Computed property namesによる分岐は不要だと思われます。Vue CLI で環境構築した場合のデフォルトは v8 になっています(記事投稿時点) 

  4. 参照: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import 

  5. 参照: https://github.com/vitejs/vite/pull/2254 


Viewing all articles
Browse latest Browse all 8960

Trending Articles