Vue 3 で Option API を無効化した場合のバンドルサイズの差異を調べたい
記事化しました。本スクラップは以下記事の下調べになってます。
Vue の README によると、Vue 3 では __VUE_OPTIONS_API__
というフィーチャーフラグをビルドタイムに注入すると、 Option API の機能を無効化することが出来るらしい。これによって Option API に関するコードがバンドルからツリーシェイキングされ、Vue本体の軽量化が出来るようなので、その実態を調べてみることにする。
この設定は webpack や rollup のバンドラから注入可能だが、Vite はバンドルに rollup を使用しているため、今回は Vite プロジェクトで試す。
また、バンドルサイズの確認には rollup-plugin-visualizer を使用する。
webpack における webpack bundle analyzer と似たようなものだと思う。
TS 用の defineComponent を使うとまた事情が変わってきそうな気配がするので、今回は JS を使って、export deafult
でピュアオブジェクトを返す方式で試す。
プロジェクトは create-vite で作成する。
$ yarn create vite vue-3-optout-option-api --template vue
今回はバンドル生成が目的なので、開発用サーバーは使わずに、ビルドとプレビューで動作を確認する。
$ yarn install
$ yarn build
$ yarn preview
いつもの
rollup-plugin-visualizer 導入する。
yarn add -D rollup-plugin-visualizer
vite から使う場合はプラグイン注入の形式で
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { visualizer } from "rollup-plugin-visualizer";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), visualizer()],
});
ビルドする
yarn build
stats.html
が生成される
ミニマムプロジェクトなので当然 Vue 本体が大半を締めてるけど、211.96KB であることがわかる。
無効化する。Vite の場合は define オプションからビルド時の環境変数を設定できる模様。
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { visualizer } from "rollup-plugin-visualizer";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), visualizer()],
define: {
__VUE_OPTIONS_API__: false,
},
});
これで再度ビルドする
190.0KB
なんかビジュアライズされた結果と実際のバンドルファイルのサイズぜんぜん違うなって思ったらそういうものらしい。
ので、Vite のログに基づく実際のファイルサイズで改めて比較する。
__VUE_OPTIONS_API__: true,
$ yarn build
yarn run v1.22.19
$ vite build
vite v4.0.3 building for production...
✓ 16 modules transformed.
dist/index.html 0.45 kB
dist/assets/vue-5532db34.svg 0.50 kB
dist/assets/index-351bd726.css 1.29 kB │ gzip: 0.66 kB
dist/assets/index-f59c7c2f.js 54.21 kB │ gzip: 21.89 kB
✨ Done in 0.78s.
__VUE_OPTIONS_API__: false,
$ yarn build
yarn run v1.22.19
$ vite build
vite v4.0.3 building for production...
✓ 16 modules transformed.
dist/index.html 0.45 kB
dist/assets/vue-5532db34.svg 0.50 kB
dist/assets/index-351bd726.css 1.29 kB │ gzip: 0.66 kB
dist/assets/index-2809b276.js 48.72 kB │ gzip: 19.75 kB
✨ Done in 0.68s.
バンドルされたJSファイルのサイズは 54.21KB から 48.72KB に。6KB の削減(gzip だと2KB 程度)
ちなみに弊社サービスのメインバンドルサイズは Brotli 形式で 178kB なので、限りなく誤差に近いことはわかってきた。
create-vite で作成されたコンポーネントは以下のように composition API で書かれてる。
<script setup>
import { ref } from 'vue'
defineProps({
msg: String,
})
const count = ref(0)
</script>
これを雑に Option API に書き直す
<script>
export default {
data: () => ({
count: 0,
}),
props: {
msg: String,
},
};
</script>
無効化した状態だとビルドも成功するコンソールエラーも出ないけど、Option API で書いたコンポーネントがリアクティブにならなくなってる。
結局何が除外されたのかだけ確認して終わろう。
__VUE_OPTIONS_API__
は __FEATURE_OPTIONS_API__
っていうフィーチャーフラグに書き換えられる
以下みたいに、不要な Option API の追加を防いでる
そういえばサードパーティライブラリが Option API を使ってたら、無効化しても基本的に駄目だよね。
Vue 3 向けだけど Option API を使ってる自分のパッケージで試す。
当然といえば当然、無効化した場合は何も表示されなくなる。このときエラーも出ないのが辛い。
vuetify 3 は全部 composition API で書かれてるかなぁ。
$ yarn add vuetify@^3.0.6
雰囲気でセットアップ
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import "vuetify/styles";
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";
const vuetify = createVuetify({
components,
directives,
});
createApp(App).use(vuetify).mount("#app");
適当にインタラクティブなコンポーネント(カルーセル) を使ってみる。
<template>
<div class="wrapper">
<v-carousel>
<v-carousel-item
src="https://cdn.vuetifyjs.com/images/cards/docks.jpg"
cover
></v-carousel-item>
<v-carousel-item
src="https://cdn.vuetifyjs.com/images/cards/hotel.jpg"
cover
></v-carousel-item>
<v-carousel-item
src="https://cdn.vuetifyjs.com/images/cards/sunshine.jpg"
cover
></v-carousel-item>
</v-carousel>
</div>
</template>
これは無効化しても動いた!
なぜなら Composition API だけで実装されてるから。
だいたい把握して計測もできたので終わり。
一応整理して記事化するかも。