✌️

Vite v5リリース! 気になるアップデート内容まとめ

2023/12/10に公開

https://vitejs.dev/guide/migration.html#rework-define-and-import-meta-env-replacement-strategy
https://vitejs.dev/blog/announcing-vite5

2023/11/16にViteのv5がリリースされました。
この記事ではv5アップデートの気になる部分をピックアップして紹介していきます。

Node.jsのサポート

Node.js 14/16/17/19はサポート外となりました。
v5からは18/20+のバージョンが必要となります。

Rollup 4

これが一番の目玉ですね。2023/10/15にRollupがv4にアップデートされ、それに追従する形でVite内部のRollupもアップデートされています。

import assertions -> attributes への移行

Import assertions (assertions prop) has been renamed to import attributes (attributes prop).

Rollupのv4マイグレーションガイドには下記のように記述されています。

If your plugin handles import assertions, note that in the resolveId hook and other places, assertions have been replaced with attributes as the JavaScript feature was also renamed.

Deepl訳:プラグインがimport assertionsを処理する場合、resolveIdフックやその他の場所でJavaScriptの機能も名前が変更されたため、assertionsがattributesに置き換えられていることに注意してください。

これはtc39でプロポーザルされ現在Stage 3にあるproposal-import-attributesのことを指しています。

import json from "./foo.json" with { type: "json" };

といった形で、import行の中にモジュールの指定子などを渡すことができる機能です。
元々import json from "./foo.json" assert { type: "json" }といった構文で提案されていましたが、2023年3月にassertからwithに記法が変更になりました。
Rollupもそれに追従する形で変更されています。

OSSのプラグインを利用している場合は、プラグイン側がv5対応したものを使うように注意してください。

Acorn プラグインのサポートの終了

Rollup v4が内部parserをacornからswcに変更しました。
それに伴ってAcornプラグインは使用できなくなります。
https://github.com/rollup/rollup/pull/5073

プラグインのthis.resolve skipSelfが デフォルトtrueに変更

RollupのプラグインではresolveIdというhookを通してimportのパスを参照しています。
https://rollupjs.org/plugin-development/#resolveid

export default function myExample() {
  return {
    name: "my-example",
    resolveId(source) {
      if (source === "virtual-module") {
        return source;
      }
      return null;
    },
    load(id) {
      if (id === "virtual-module") {
        return 'export default "This is virtual!"';
      }
    },
  };
}

this.resolve()はresolveIdなどのhookから呼ぶことのできる関数です。

moduleがexternalであるかどうかなどの情報を取得することができますが、
元々はthis.resolveによってresolveIdが発火する仕様になっており、再帰が無限に発火しないようにコントロールする必要がありました。
今回のRollup v4へのアップデートによって、this.resolveによってresolveIdが発火しないようになるskipSelfオプションがdefaultでtrueになるという変更です。

Deprecate CJS Node API

Viteの Node APIがCJS非対応になりました。
CJSでコンパイルできない!という意味ではないのでご注意を。
マイグレーションで必要な対応は下記になります。

  1. vite.config.jsはESM構文で記述する
  2. 拡張子対応
       a. ESMをデフォルトとして扱う場合、package.jsonのファイルに"type: "module"を記述し、CSJ記述ファイルの拡張子を.cjsと変更する。
    b. CJSをデフォルトとして扱う場合、vite.configに.mjs/.mts拡張子をつける

defineimport.meta.env.*の置換方法の再設計

defineはvite.configでグローバル定数を指定できるオプションです。
import.meta.env.*はVite側が公開するグローバルオブジェクト群で、組み込みのものもあれば.envファイル経由で指定できるものもあります。

VITE_SOME_KEY=123 // import.meta.env.*経由で公開するにはVITE_接頭辞をつける
console.log(import.meta.env.VITE_SOME_KEY) // 123

つまり現状ユーザーがグローバルな値を指定したい場合、defineimport.meta.env.*の二つの方法があります。
どちらの機能もVite v4 では開発時・ビルド時でそれぞれ異なる置換方法を採用していました。
開発時・・・globalThis/import.metaにグローバル変数として挿入される
ビルド時・・・正規表現によって静的に置換される

これによって、開発時とビルド時で整合性が取れずビルドが失敗することがありました。

const data = { __APP_VERSION__ }
// 開発中: { __APP_VERSION__: "1.0.0" } ✅ // グローバル変数として挿入
// ビルド時: { "1.0.0" } ❌ // 静的に置換されるのでオブジェクトとして不正な値に

Vite v5ではビルド時と開発時の挙動が同じになるよう調整されています。🎈
@rollup/plugin-replaceというプラグインを使用することで静的な置換にロールバックできる救済処置もあるようです。

server.warmup

https://vitejs.dev/guide/performance#warm-up-frequently-used-files

起動時間の改善のための機能として、server.warmupが導入されました。
開発サーバーにおいてViteは予め全てのファイルを変換せず、リクエストされたファイルのみを変換することで素早く起動できるようになっています。
しかし、実行中に重いファイルの変換処理が走ると他のファイルの読み込みを阻害することがあります。

server.warmupでファイルを指定すると、開発中よく使われる重いファイルを事前ウォームアップできます。

下記のように記述できます。

export default defineConfig({
  server: {
    warmup: {
      clientFiles: [
        './src/components/BigComponent.vue',
        './src/utils/big-utils.js',
      ],
    },
  },
})

Discussion