Single-File Components - Vueコンポーネントの標準単位

ロードマップ: Vue.js学習ロードマップ

What(何についてか)

Vue の Single-File Components(SFC)は、.vue ファイル 1 つの中に templatescriptstyle をまとめて記述するコンポーネント形式である。

<script setup>
import { ref } from 'vue'
 
const greeting = ref('Hello World!')
</script>
 
<template>
  <p class="greeting">{{ greeting }}</p>
</template>
 
<style>
.greeting {
  color: red;
  font-weight: bold;
}
</style>

この形式では、1コンポーネントを「見た目」「振る舞い」「スタイル」のまとまりとして扱う。

Why(なぜ必要か)

Vue では関心の分離を「HTML / CSS / JavaScript のファイル種別で分けること」ではなく、「コンポーネント単位で保守しやすく分けること」と捉える。

そのため SFC には次の利点がある。

  • UI、ロジック、スタイルをコンポーネント単位で閉じ込められる
  • <script setup> と Composition API を自然に書ける
  • テンプレートを事前コンパイルできるため、実行時コストを減らせる
  • template と script を横断した最適化、型支援、補完が効きやすい
  • HMR や scoped CSS など、Vue の開発体験の中心機能を活かしやすい

小さな静的ページに少量の振る舞いを足すだけなら SFC なしでもよいが、SPA / SSG / 中規模以上のフロントエンドでは SFC が標準になる。

How(どう動くか)

.vue ファイルはブラウザがそのまま実行する形式ではなく、ビルド時に標準的な JavaScript / CSS に変換される。

flowchart TD
  A["MyComponent.vue を作成"] --> B["@vue/compiler-sfc が解析"]
  B --> C["template を render 関数へ変換"]
  B --> D["script / script setup を JS module として処理"]
  B --> E["style を開発時注入 / 本番時抽出"]
  C --> F["最終的に ES module 化"]
  D --> F
  E --> F

開発者視点では .vue を通常のモジュールのように import できる。

import MyComponent from './MyComponent.vue'
 
export default {
  components: {
    MyComponent
  }
}

この背後では、以下のような役割分担がある。

  • @vue/compiler-sfc: SFC 解析と変換の中核
  • @vitejs/plugin-vue: Vite 環境で .vue を扱うための接続層
  • vue-loader: webpack 系で .vue を扱うための接続層

In-Browser Template Compilation

Vue には、テンプレートコンパイラを含むフルビルドと、含まない runtime-only build がある。

  • SFC + build step
    • テンプレートはビルド時に事前コンパイルされる
    • runtime-only build が基本になる
  • ビルドなしで HTML に直接テンプレートを書く場合
    • ブラウザ内でテンプレートを解釈する必要がある
    • compiler を含むフルビルドが必要になる

Vue 3 の通常開発では、前者が標準である。

Separation of Concerns の捉え方

Vue の立場では、関心の分離の目的は保守性の向上である。したがって、巨大な HTML/CSS/JS の層に分けるより、コンポーネントごとに関係するコードをまとめる方が保守しやすい。

ファイル種別ベースの分離

  • HTML ファイル群
  • CSS ファイル群
  • JS ファイル群

この形では、1つの部品を修正するために複数ファイルを横断しやすい。

コンポーネントベースの分離

  • Button.vue
  • Modal.vue
  • UserCard.vue

この形では、それぞれの部品の責務がローカルに閉じる。

SFC Custom Block Integrations

SFC では <template>, <script>, <style> 以外の独自ブロックも拡張として扱える。

<docs>
このコンポーネントの説明
</docs>

このような custom block は SFC 自体が意味を理解するわけではなく、Vite plugin や webpack loader など下位ツール側が解釈を担当する。標準開発で多用するものではないが、SFC が拡張可能な器であることを示している。

実務での判断軸

  • Vue 3 の標準開発単位は コンポーネント である
  • その標準的な器が SFC (.vue) である
  • 新規開発では SFC + build step + runtime-only build を前提に考える
  • 小さな progressive enhancement では plain JavaScript や petite-vue も選択肢になる
  • Vue の学習や実務では、SFC は単なる記法ではなく、ツールチェーン全体の中心概念である

Options API → Composition API 差分(補足)

項目Options API(旧)Composition API(新)
ロジックの入口data, methods, computed に分散<script setup> 内で近接して記述
this 依存this を前提に値へアクセスref, reactive, 関数を直接参照
再利用の単位mixins などに寄りやすいcomposables に寄せやすい
SFC との相性書けるが記述量が増えやすいSFC 内で最も自然に書ける

Key Concepts

用語説明
SFCVue の .vue 形式のコンポーネントファイル
<script setup>Composition API を簡潔に記述するための SFC 構文
runtime-only buildテンプレートコンパイラを含まない軽量ビルド
@vue/compiler-sfcSFC を解析、変換するコアパッケージ
@vitejs/plugin-vueVite で Vue SFC を扱うための公式プラグイン
vue-loaderwebpack 系で Vue SFC を扱うための公式 loader
custom block<template>, <script>, <style> 以外の独自ブロック