- Vue.js
Vue UIライブラリ比較|6種で同じ画面を作りサイズを実測
Vue UIライブラリとは、ボタン・入力欄・表・ダイアログなどの画面部品をまとめて提供し、見た目と操作感のそろった画面を速く作るためのライブラリです。 代表的なものに Vuetify、PrimeVue、Element Plus、Quasar、Nuxt UI、Naive UI があり、それぞれ得意な場面が違います。
この記事では、2026年9月28日時点の最新版(Vuetify 4.2.2、PrimeVue 5.0.1、Element Plus 2.14.6、Quasar 2.33.2、Nuxt UI 4.11.2、Naive UI 2.45.3)で「入力フォーム+データテーブル+ダイアログ」という同じ画面を実際に作り、Vite 8.3.1 でビルドしたJS/CSSのサイズ(gzip)を測りました。さらに「全部まとめて登録」と「使う部品だけ読み込む」でサイズがどう変わるか、Playwright で画面操作が通るかも確認しています。目的別の選び方フローと、コピペで動く最小コードもまとめました。
Vue UIライブラリ比較の早見表
| ライブラリ | 最新版(npm) | デザインの系統 | 部品数の目安※1 | 日本語化 | Nuxtでの使い方 | ライセンス | 安定版リリース数(直近6か月)※2 | 向いている場面 |
|---|---|---|---|---|---|---|---|---|
| Vuetify | 4.2.2 | マテリアルデザイン | 約190 | 同梱(vuetify/locale の ja) |
vuetify-nuxt-module(コミュニティ) | MIT | 35 | 部品の多さと一貫したデザインを重視する業務画面 |
| PrimeVue | 5.0.1 | テーマ選択式(Aura など) | 約190 | locale オプションで設定(訳語は別パッケージ primelocale など) |
@primevue/nuxt-module(公式) | PrimeUIライセンス(v5〜)※3 | 3 | 高機能なデータテーブルや入力部品が多い画面 |
| Element Plus | 2.14.6 | シンプルな業務UI | 約120 | 同梱(element-plus/es/locale/lang/ja) |
@element-plus/nuxt(公式) | MIT | 8 | 管理画面・社内ツールを手早く作る |
| Quasar | 2.33.2 | マテリアル寄り | 約120 | 同梱(quasar/lang/ja) |
nuxt-quasar-ui(コミュニティ) | MIT | 34 | SPA・PWA・モバイル・デスクトップを1つのコードで |
| Nuxt UI | 4.11.2 | Tailwind CSS ベース | 約120 | 同梱(@nuxt/ui/locale の ja) |
@nuxt/ui そのものがNuxtモジュール | MIT | 11 | Nuxt・Tailwind CSS 中心の新規開発(Vue単体でも可) |
| Naive UI | 2.45.3 | すっきりした独自デザイン | 約150 | 同梱(jaJP・dateJaJP) |
コミュニティモジュール | MIT | 4 | TypeScript で書きたい中規模の画面、CSS不要で導入したい |
| shadcn-vue | 2.8.2(CLI) | Tailwind CSS + Reka UI | 必要な部品をコピー | 自分で実装 | shadcn-nuxt | MIT | 15 | 部品のコードを手元に置いて自由に改造したい |
※1 本記事でパッケージ内のエクスポートやファイルを数えた値です。子部品を含むため目安としてご覧ください。
※2 npm の公開履歴から、2026-03-29〜09-28 の安定版の数を数えました。
※3 PrimeVue 5 から「PrimeUIライセンス」になりました(4.x は MIT のまま)。詳しくは後述の「PrimeVue 5 のライセンスと導入時の確認」をご覧ください。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Vue UIライブラリ比較|6種で同じ画面を作りサイズを実測」
同じ画面を作ってビルドサイズを実測した結果
同じ画面でも、ライブラリと「読み込み方」によってJS+CSSのサイズは約120KB〜約390KB(gzip)まで変わりました。 そして、全部登録から「使う部品だけ」に切り替えると、41〜61%小さくなりました。
検証の条件
| 項目 | 内容 |
|---|---|
| 実行環境 | Node.js 22.22.2 / Linux |
| 共通 | vue 3.5.43、vite 8.3.1、@vitejs/plugin-vue 6.0.9 |
| 作った画面 | 入力欄+選択+「追加」ボタン、3列×3行の表、「詳細を開く」で開くダイアログ |
| 計測値 | vite build が出力する gzip サイズ(JS と CSS の合計) |
| 動作確認 | ビルド結果を静的サーバーで配信し、Playwright 1.56.1(Chromium)で「入力→追加→表に行が増える」「ダイアログが開く→閉じる」を自動操作 |
| 除外したもの | アイコンフォント・Webフォント(全構成で未追加) |
計測結果(gzip、小さい順)
| 構成 | 読み込み方 | JS | CSS | 合計 | Playwright |
|---|---|---|---|---|---|
| 素のVue(比較用) | HTML要素だけ | 26.23 kB | - | 26.23 kB | 3操作すべて成功 |
| Quasar | @quasar/vite-plugin(使う分だけ) | 87.33 kB | 36.39 kB | 123.72 kB | 3操作すべて成功 |
| Element Plus | 使う分だけ(unplugin-vue-components) | 128.52 kB | 12.74 kB | 141.26 kB | 3操作すべて成功 |
| PrimeVue | 部品ごとに import(標準の書き方) | 164.59 kB | -(JS内でスタイル生成) | 164.59 kB | 3操作すべて成功 |
| Naive UI | 部品ごとに import | 165.93 kB | -(CSS-in-JS) | 165.93 kB | 3操作すべて成功 |
| Vuetify | 使う分だけ(vite-plugin-vuetify) | 140.10 kB | 43.26 kB | 183.36 kB | 3操作すべて成功 |
| Nuxt UI | @nuxt/ui/vite(使う分だけ) | 164.15 kB | 25.25 kB | 189.40 kB | 3操作すべて成功 |
| Vuetify | 全部登録 | 246.82 kB | 67.90 kB | 314.72 kB | 3操作すべて成功 |
| Element Plus | 全部登録(app.use(ElementPlus)) |
316.43 kB | 47.94 kB | 364.37 kB | 3操作すべて成功 |
| Naive UI | 全部登録(app.use(naive)) |
387.17 kB | - | 387.17 kB | 3操作すべて成功 |
Playwright の実行ログ(抜粋)です。10構成すべてで操作が通りました。
plain: 追加OK / ダイアログ表示OK / 閉じるOK
vuetify-full: 追加OK / ダイアログ表示OK / 閉じるOK
primevue: 追加OK / ダイアログ表示OK / 閉じるOK
warning: [PrimeUI] PrimeUI license is not configured.
element-auto: 追加OK / ダイアログ表示OK / 閉じるOK
nuxtui: 追加OK / ダイアログ表示OK / 閉じるOK
error: Failed to load resource: net::ERR_TUNNEL_CONNECTION_FAILED
(ほかの5構成も同じく3操作OK)
2つのメッセージは、この後の「つまずきやすいポイント」で理由と対処を説明します。
結果の読み取り方
- 差を生む一番の要因は「全部登録」か「使う分だけ」かです。Element Plus は 364.37 kB → 141.26 kB(61.2%減)、Naive UI は 387.17 kB → 165.93 kB(57.1%減)、Vuetify は 314.72 kB → 183.36 kB(41.7%減)でした。
- ライブラリどうしの差は、使う分だけにそろえると約120〜190 kB の範囲に収まりました。1画面だけの小さな検証なので、部品を増やしたときの伸び方は構成によって変わります。
- 値にはVue本体(素のVueで26.23 kB)が含まれます。ライブラリ分は約26 kB を引いてください。
- PrimeVue と Naive UI はスタイルをJSの中で生成する方式なので、CSSファイルが出ません。その分がJSの値に含まれます。
- 全部登録の構成では、Vite が「500 kB を超えるチャンク」の警告を出しました(後述)。
個別インポートでサイズを小さくする方法
多くのライブラリは、Viteプラグインか resolver を入れるだけで「テンプレートに書いた部品だけ」を自動で読み込めます。 コードの書き方はほぼ変わりません。
| ライブラリ | 全部登録の書き方 | 使う分だけにする方法 | 今回の削減率 |
|---|---|---|---|
| Vuetify | createVuetify({ components, directives }) |
vite-plugin-vuetify の autoImport: true |
41.7% |
| Element Plus | app.use(ElementPlus) + index.css |
unplugin-vue-components + ElementPlusResolver(CSSも必要分だけ) |
61.2% |
| Naive UI | app.use(naive) |
import { NButton } from 'naive-ui' を部品ごとに書く |
57.1% |
| PrimeVue | (部品ごとの import が標準) | @primevue/auto-import-resolver で import 文も省略可 |
- |
| Quasar | - | @quasar/vite-plugin が自動で使う分だけにする |
- |
| Nuxt UI | - | @nuxt/ui/vite が自動で使う分だけにする |
- |
今回使った Vite の設定です(1つの設定ファイルを環境変数で切り替えています)。
// vite.config.ts(vite 8.3.1)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vuetify from 'vite-plugin-vuetify'
import { quasar, transformAssetUrls } from '@quasar/vite-plugin'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import ui from '@nuxt/ui/vite'
const APP = process.env.APP!
const plugins: any[] = []
if (APP === 'quasar') {
plugins.push(vue({ template: { transformAssetUrls } }), quasar())
} else {
plugins.push(vue())
}
if (APP === 'vuetify-auto') plugins.push(vuetify({ autoImport: true }))
if (APP === 'element-auto') plugins.push(Components({ resolvers: [ElementPlusResolver()], dts: false }))
if (APP === 'nuxtui') plugins.push(ui())
export default defineConfig({
root: `apps/${APP}`,
plugins,
build: { outDir: `../../dist/${APP}`, emptyOutDir: true },
})
# 例:Element Plus の「使う分だけ」版をビルド
APP=element-auto npx vite build
ポイントは、package.json に "type": "module" を入れておくことです。入れずに実行すると、次の「つまずきやすいポイント」にあるエラーになりました。
目的別の選び方フロー
迷ったら「Nuxtを使うか」「Tailwind CSSを使うか」「どんな画面が中心か」の3つで絞ると決めやすくなります。
flowchart TD
A[Vue UIライブラリを選ぶ] --> B{Nuxtで作る?}
B -- はい --> C{Tailwind CSSを使う?}
C -- はい --> D[Nuxt UI / shadcn-vue]
C -- いいえ --> E[Vuetify / PrimeVue / Element Plus]
B -- いいえ(Vue + Vite) --> F{画面の中心は?}
F -- 表・入力が多い業務画面 --> G[Element Plus / PrimeVue / Vuetify]
F -- スマホ・PWA・デスクトップも --> H[Quasar]
F -- 部品を自分で改造したい --> I[shadcn-vue]
F -- TypeScript中心で軽く導入 --> J[Naive UI]
| やりたいこと | 候補 | 理由 |
|---|---|---|
| マテリアルデザインで統一したい | Vuetify、Quasar | どちらもマテリアル系のデザインが基本 |
| 高機能な表(並べ替え・絞り込み・固定列など)が中心 | PrimeVue、Vuetify、Element Plus | データテーブルの機能が豊富 |
| 管理画面を最短で作りたい | Element Plus | 部品の見た目が控えめで、フォーム・表の組み合わせが作りやすい |
| 1つのコードでWeb・スマホ・デスクトップ | Quasar | Quasar CLI がPWA・モバイル・Electron向けビルドに対応 |
| Nuxtと一体で使いたい | Nuxt UI | Nuxt公式のモジュールで、設定がほぼ不要 |
| Tailwind CSSで見た目を細かく変えたい | Nuxt UI、shadcn-vue | Tailwind のクラスで見た目を調整できる |
| ライセンスをMITでそろえたい | PrimeVue 以外、または PrimeVue 4.x | PrimeVue 5 は PrimeUIライセンス |
インストールから最小コードまでのコピペ集
ここのコードは、すべて今回のビルドとPlaywrightの確認に使ったものです(shadcn-vue のみ未実行)。各 <script setup> には次の共通コードを書いています。
// 各 App.vue の <script setup lang="ts"> に共通で書いたコード
import { ref } from 'vue'
const name = ref('')
const category = ref('備品')
const categories = ['備品', '書籍', 'その他']
const rows = ref([
{ id: 1, name: 'ノートPC', category: '備品' },
{ id: 2, name: 'Vue入門', category: '書籍' },
{ id: 3, name: 'ホワイトボード', category: '備品' },
])
const open = ref(false)
function add() {
if (!name.value) return
rows.value = [...rows.value, { id: rows.value.length + 1, name: name.value, category: category.value }]
name.value = ''
}
Vuetify 4
npm i vuetify
npm i -D vite-plugin-vuetify
// main.ts(vite.config.ts で vuetify({ autoImport: true }) を登録)
import { createApp } from 'vue'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import App from './App.vue'
createApp(App).use(createVuetify()).mount('#app')
<script setup lang="ts">
// 共通コード(上記)+列定義
const headers = [
{ title: 'ID', key: 'id' },
{ title: '名前', key: 'name' },
{ title: 'カテゴリ', key: 'category' },
]
</script>
<template>
<v-app>
<v-main>
<v-container>
<v-form @submit.prevent="add">
<v-text-field v-model="name" label="名前" placeholder="名前を入力" />
<v-select v-model="category" :items="categories" label="カテゴリ" />
<v-btn type="submit" color="primary">追加</v-btn>
</v-form>
<v-data-table :headers="headers" :items="rows" />
<v-btn @click="open = true">詳細を開く</v-btn>
<v-dialog v-model="open" max-width="400">
<v-card title="確認" text="ダイアログの本文です">
<v-card-actions><v-btn @click="open = false">閉じる</v-btn></v-card-actions>
</v-card>
</v-dialog>
</v-container>
</v-main>
</v-app>
</template>
PrimeVue 5
npm i primevue @primeuix/themes
// main.ts
import { createApp } from 'vue'
import PrimeVue from 'primevue/config'
import Aura from '@primeuix/themes/aura'
import App from './App.vue'
createApp(App).use(PrimeVue, { theme: { preset: Aura } }).mount('#app')
<script setup lang="ts">
import InputText from 'primevue/inputtext'
import Select from 'primevue/select'
import Button from 'primevue/button'
import DataTable from 'primevue/datatable'
import Column from 'primevue/column'
import Dialog from 'primevue/dialog'
// 共通コード(上記)
</script>
<template>
<form @submit.prevent="add">
<InputText v-model="name" placeholder="名前を入力" />
<Select v-model="category" :options="categories" />
<Button type="submit" label="追加" />
</form>
<DataTable :value="rows">
<Column field="id" header="ID" />
<Column field="name" header="名前" />
<Column field="category" header="カテゴリ" />
</DataTable>
<Button label="詳細を開く" @click="open = true" />
<Dialog v-model:visible="open" header="確認" modal>
<p>ダイアログの本文です</p>
<Button label="閉じる" @click="open = false" />
</Dialog>
</template>
Element Plus
npm i element-plus
npm i -D unplugin-vue-components
// main.ts(「使う分だけ」版。部品とCSSは ElementPlusResolver が自動で読み込む)
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
<script setup lang="ts">
import ja from 'element-plus/es/locale/lang/ja'
// 共通コード(上記)
</script>
<template>
<el-config-provider :locale="ja">
<el-form label-width="auto" @submit.prevent="add">
<el-form-item label="名前"><el-input v-model="name" placeholder="名前を入力" /></el-form-item>
<el-form-item label="カテゴリ">
<el-select v-model="category"><el-option v-for="c in categories" :key="c" :label="c" :value="c" /></el-select>
</el-form-item>
<el-button type="primary" native-type="submit">追加</el-button>
</el-form>
<el-table :data="rows">
<el-table-column prop="id" label="ID" />
<el-table-column prop="name" label="名前" />
<el-table-column prop="category" label="カテゴリ" />
</el-table>
<el-button @click="open = true">詳細を開く</el-button>
<el-dialog v-model="open" title="確認" width="400">
<p>ダイアログの本文です</p>
<el-button @click="open = false">閉じる</el-button>
</el-dialog>
</el-config-provider>
</template>
Quasar(Vite プラグイン)
npm i quasar @quasar/extras
npm i -D @quasar/vite-plugin sass-embedded
// main.ts(vite.config.ts で vue({ template: { transformAssetUrls } }) と quasar() を登録)
import { createApp } from 'vue'
import { Quasar } from 'quasar'
import langJa from 'quasar/lang/ja'
import 'quasar/src/css/index.sass'
import App from './App.vue'
createApp(App).use(Quasar, { lang: langJa }).mount('#app')
<script setup lang="ts">
// 共通コード(上記)+列定義
const columns = [
{ name: 'id', label: 'ID', field: 'id', align: 'left' as const },
{ name: 'name', label: '名前', field: 'name', align: 'left' as const },
{ name: 'category', label: 'カテゴリ', field: 'category', align: 'left' as const },
]
</script>
<template>
<div class="q-pa-md">
<q-form @submit="add">
<q-input v-model="name" label="名前" placeholder="名前を入力" outlined />
<q-select v-model="category" :options="categories" label="カテゴリ" outlined />
<q-btn type="submit" color="primary" label="追加" />
</q-form>
<q-table :rows="rows" :columns="columns" row-key="id" />
<q-btn label="詳細を開く" @click="open = true" />
<q-dialog v-model="open">
<q-card>
<q-card-section>ダイアログの本文です</q-card-section>
<q-card-actions><q-btn flat label="閉じる" @click="open = false" /></q-card-actions>
</q-card>
</q-dialog>
</div>
</template>
Nuxt UI 4(Nuxtを使わないVue + Viteで)
Nuxt UI は Nuxt 専用ではなく、Vue + Vite でも使えます。 公式の Vue 向け手順どおり、Vite プラグイン @nuxt/ui/vite と Vue プラグイン @nuxt/ui/vue-plugin を登録します。
npm i @nuxt/ui tailwindcss vue-router
/* main.css */
@import "tailwindcss";
@import "@nuxt/ui";
// main.ts(vite.config.ts で ui() を登録。index.html の <div id="app"> に class="isolate")
import './main.css'
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import ui from '@nuxt/ui/vue-plugin'
import App from './App.vue'
const router = createRouter({ routes: [], history: createWebHistory() })
createApp(App).use(router).use(ui).mount('#app')
<script setup lang="ts">
// 共通コード(上記)+列定義(TanStack Table 形式)
const columns = [
{ accessorKey: 'id', header: 'ID' },
{ accessorKey: 'name', header: '名前' },
{ accessorKey: 'category', header: 'カテゴリ' },
]
</script>
<template>
<UApp>
<form class="flex gap-2 p-4" @submit.prevent="add">
<UFormField label="名前"><UInput v-model="name" placeholder="名前を入力" /></UFormField>
<UFormField label="カテゴリ"><USelect v-model="category" :items="categories" class="w-40" /></UFormField>
<UButton type="submit" label="追加" />
</form>
<UTable :data="rows" :columns="columns" />
<UModal v-model:open="open" title="確認">
<UButton label="詳細を開く" />
<template #body>
<p>ダイアログの本文です</p>
<UButton label="閉じる" @click="open = false" />
</template>
</UModal>
</UApp>
</template>
vue-router なしなら ui({ router: false }) も選べます(型定義で確認)。
Naive UI
npm i naive-ui
<script setup lang="ts">
import { NConfigProvider, NForm, NFormItem, NInput, NSelect, NButton, NDataTable, NModal } from 'naive-ui'
// 共通コード(上記)+選択肢と列定義
const options = categories.map((c) => ({ label: c, value: c }))
const columns = [
{ title: 'ID', key: 'id' },
{ title: '名前', key: 'name' },
{ title: 'カテゴリ', key: 'category' },
]
</script>
<template>
<n-config-provider>
<n-form @submit.prevent="add">
<n-form-item label="名前"><n-input v-model:value="name" placeholder="名前を入力" /></n-form-item>
<n-form-item label="カテゴリ"><n-select v-model:value="category" :options="options" /></n-form-item>
<n-button type="primary" attr-type="submit">追加</n-button>
</n-form>
<n-data-table :columns="columns" :data="rows" />
<n-button @click="open = true">詳細を開く</n-button>
<n-modal v-model:show="open" preset="card" title="確認" style="width: 400px">
<p>ダイアログの本文です</p>
<n-button @click="open = false">閉じる</n-button>
</n-modal>
</n-config-provider>
</template>
main.ts は createApp(App).mount('#app') だけで動きます。
shadcn-vue(未実行)
shadcn-vue は npm パッケージを読み込むのではなく、部品のソースコードを自分のプロジェクトにコピーする方式です。Tailwind CSS と Reka UI が前提になります。本記事では実行していないため、公式ドキュメントの手順を確認してから導入してください。
# 公式ドキュメントの手順(本記事では未実行)
npx shadcn-vue@latest init
npx shadcn-vue@latest add button dialog table
日本語化(i18n)の設定
日付選択やページ送りなど、部品の中に出る文言は各ライブラリの言語設定で日本語にできます。 Vuetify・Element Plus・Quasar・Nuxt UI・Naive UI は日本語の言語データを同梱しています(ファイルの存在を確認済み)。
| ライブラリ | 設定方法 |
|---|---|
| Vuetify | import { ja } from 'vuetify/locale' → createVuetify({ locale: { locale: 'ja', messages: { ja } } }) |
| PrimeVue | app.use(PrimeVue, { locale: { ... } }) に訳語を渡す(パッケージに日本語データは入っていないため、primelocale などから取得) |
| Element Plus | import ja from 'element-plus/es/locale/lang/ja' → app.use(ElementPlus, { locale: ja }) または <el-config-provider :locale="ja"> |
| Quasar | import langJa from 'quasar/lang/ja' → app.use(Quasar, { lang: langJa }) |
| Nuxt UI | import { ja } from '@nuxt/ui/locale' → <UApp :locale="ja"> |
| Naive UI | import { jaJP, dateJaJP } from 'naive-ui' → <n-config-provider :locale="jaJP" :date-locale="dateJaJP"> |
Nuxtで使う場合のモジュール
Nuxt では各ライブラリ用のモジュールで、部品の自動インポートやSSR向け設定をまとめて任せられます。
| ライブラリ | モジュール(npm) | 提供元 |
|---|---|---|
| Nuxt UI | @nuxt/ui(4.11.2) |
Nuxt 公式 |
| PrimeVue | @primevue/nuxt-module(5.0.1) |
PrimeVue 公式 |
| Element Plus | @element-plus/nuxt(1.1.5) |
Element Plus 公式 |
| Vuetify | vuetify-nuxt-module(latest タグは 1.0.0-rc.6) |
コミュニティ |
| Quasar | nuxt-quasar-ui(3.1.1) |
コミュニティ |
| shadcn-vue | shadcn-nuxt(2.8.2) |
shadcn-vue |
PrimeVue 5 のライセンスと導入時の確認
PrimeVue 5.0.0(2026年7月公開)から、ライセンスが MIT から「PrimeUIライセンス」に変わりました。 公式の移行ガイドでは、4.x からのアップグレードで公開APIの破壊的変更はないと案内されています。導入前に、次の点を確認しておくと安心です。
| 確認すること | 内容(2026-09-28 時点、公式発表とパッケージ同梱の LICENSE.md より) |
|---|---|
| 無料で使える条件 | Community License:年間売上100万ドル未満・開発者5名未満・従業員10名未満・外部資金300万ドル未満のすべてを満たす組織、個人・学生・非営利・非商用OSS |
| それ以外 | Commercial License(開発者単位の買い切り、1年分の更新付き) |
| ライセンスキー | 設定が必要。キーの確認はオフラインで行われ、外部通信はしないと記載 |
| 既存バージョン | MIT で公開済みの 4.x は MIT のまま |
実際にキーを設定せずに動かすと、画面の操作はすべて通り、ブラウザのコンソールに次の警告が出ました。
warning: [PrimeUI] PrimeUI license is not configured.
キーは app.use(PrimeVue, { license: '...' }) の license オプションで渡します(型定義で確認)。条件や価格は変わることがあるため、採用を決める前に公式サイトの最新の条件を確認し、チームで合意しておくとスムーズです。
つまずきやすいポイントと対処
今回の検証で実際に出たメッセージと、その直し方です。
| 出たメッセージ | 原因 | 対処 |
|---|---|---|
Failed to resolve "@quasar/vite-plugin". This package is ESM only but it was tried to load by require. |
package.json に "type": "module" がなく、設定ファイルが CommonJS として読まれた |
npm pkg set type=module を実行(または vite.config.mts にする) |
[PrimeUI] PrimeUI license is not configured. |
PrimeVue 5 のライセンスキーが未設定 | 条件を確認し、license オプションにキーを設定 |
Nuxt UI で ERR_TUNNEL_CONNECTION_FAILED(api.iconify.design/lucide.json?icons=check,chevron-down への通信) |
Vue 版の Nuxt UI は、USelect などのアイコンを実行時に Iconify API から取得する。今回の環境は外部通信ができないため失敗 |
画面の操作には影響なし。社内ネットワークなど外部に出られない環境では、アイコンの読み込み方法を公式ドキュメントで確認して設定する |
(!) Some chunks are larger than 500 kB after minification. |
全部登録で、使っていない部品までバンドルされた | 前述の「使う分だけ」の方法に切り替える |
よくある質問
Q. 結局どれが一番おすすめですか? A. 画面の種類とチームの前提で変わります。Nuxt と Tailwind CSS なら Nuxt UI、表と入力が多い業務画面なら Element Plus・PrimeVue・Vuetify、スマホアプリやデスクトップまで1つのコードで作るなら Quasar が候補になります。候補を2つに絞ったら、本記事のように同じ画面を作って比べるのが確実です。
Q. Nuxt UI は Nuxt がなくても使えますか?
A. 使えます。@nuxt/ui/vite と @nuxt/ui/vue-plugin を登録すれば Vue + Vite で動き、本記事でもビルドと操作を確認しました。Tailwind CSS 4 が前提で、アイコンは実行時に Iconify API から取得される点を覚えておくと安心です。
Q. バンドルサイズはどれくらい気にすべきですか? A. まず「使う分だけ」の設定にすることが大切です(今回41〜61%の差)。ライブラリ間の差(約120〜190 kB)は、部品数や機能と合わせて判断するとよいでしょう。
まとめ
- Vue UIライブラリは、部品の多さ・デザイン・Nuxt対応・ライセンスで向いている場面が分かれます。
- 同じ画面でも、全部登録から「使う分だけ」にすると41〜61%小さくなりました(Element Plus 364.37 kB → 141.26 kB)。
- 使う分だけにそろえると、6ライブラリは約120〜190 kB(gzip、Vue本体込み)に収まりました。
- Nuxt UI は Vue + Vite でも使え、Nuxt では公式モジュールとして最も手軽に導入できます。
- PrimeVue 5 は PrimeUIライセンスです。条件を確認してから採用を決めましょう(4.x は MIT)。
- 日本語化は言語設定1〜2行で対応できます。
- 迷ったら候補を2つに絞り、自分の画面で作って測るのが確実です。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Vue UIライブラリ比較|6種で同じ画面を作りサイズを実測」
株式会社RJCでは、画面づくりに合ったライブラリを選び、実際に作って比べる進め方を、プロジェクトの中で仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。