SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ますます便利になるVue.jsの新機能を探ろう!

Vue.js3.4~3.5の新機能をまとめて紹介! 新しいAPIやSSRの改善

Vue3.4~3.5の新機能まとめ

SSRにおける改善

 バージョン3.4と3.5で、SSRのハイドレーションに関する幾つかの問題点も改善されています。本節では、それらを紹介していきます。なお、SSRに関しては、Vue単体での実現は難しく、Nuxtを利用するのが現実的です。そのため、本節の内容もNuxtを基本として解説します。

ハイドレーションミスマッチに関する改善

 Nuxtの場合は、単純なSSRではなく、ユニバーサルレンダリング(SSRとCSRを組み合わせたレンダリング)を基本としています。その場合、サーバサイドでのレンダリングとクライアントサイドでのレンダリングに違いがでてしまう問題、つまり、ハイドレーションミスマッチの問題が常につきまといます。その際のエラーメッセージが、バージョン3.4でわかりやすいものへと変更されました(図4)。

図4:ハイドレーションミスマッチの際のエラーメッセージ例
図4:ハイドレーションミスマッチの際のエラーメッセージ例

 図4の例は、リスト8のようなテンプレートブロック記述のコンポーネントを表示させた場合の例です。リスト8の(2)で表示させている変数randは、スクリプトブロックで生成した乱数です。ということは、コンポーネントがレンダリングされるたびに(2)の表示内容は変わります。ユニバーサルレンダリングの場合、サーバ側でレンダリングした内容とクライアント側でレンダリングした内容が変わってきます。図4中に確認できる「rendered on server」と「expected on client」というメッセージは、まさにハイドレーションミスマッチを具体的に表した内容となっています。

[リスト8]乱数を表示させるコンポーネントのテンプレートブロック
<section>
  <h4>乱数の表示</h4>  // (1)
  <p>生成した乱数は{{rand}}</p>  // (2)
</section>

 このハイドレーションミスマッチに関して、今回の乱数表示のように、あらかじめミスマッチが起こりうることが想定されており、そもそもエラーメッセージの表示が不要な場合もあります。そのような場合に記述する属性として、data-allow-mismatchがバージョン3.5で導入されました。例えば、リスト8の(2)に対して、次のコードを記述すると、図4のエラーメッセージは表示されなくなります。

<p data-allow-mismatch>生成した乱数は{{rand}}</p>

一意のid属性値を生成するuseId()

 例えば、リスト8のコンポーネントひとつの画面に複数埋め込むことを考えます。その際に、(1)のh4タグと(2)のpタグにid属性を付与したいとすると、レンダリングされた画面全体においてユニークな値を付与できる仕組みが必要となります。これを実現できる関数として、useId()がバージョン3.5で導入されました。

 これを利用して、例えば、リスト9のようなRandSectionコンポーネントを定義したとします。(1)と(2)のように、useId()で取得した値を、(3)と(4)のようにid属性としています。

[リスト9]useId()を利用したRandSectionコンポーネント
<script setup lang="ts">
  :
const idH4 = useId();  // (1)
const idP = useId();  // (2)
</script>
<template>
  <section>
    <h4 v-bind:id="idH4">乱数の表示</h4>  // (3)
    <p v-bind:id="idP" data-allow-mismatch>生成した乱数は{{rand}}</p>  // (4)
  </section>
</template>

 このRandSectionを2個埋め込んだ画面をレンダリングした場合、リスト10の通りになります。適切にユニークなid属性値が割り当てられているのがわかります。

[リスト10]RandSectionコンポーネントを2個レンダリングした結果
<section>
  <h4 id="v-0">乱数の表示</h4>
  <p id="v-1">生成した乱数は46</p>
</section>
<section>
  <h4 id="v-2">乱数の表示</h4>
  <p id="v-3">生成した乱数は49</p>
</section>

非同期コンポーネントとハイドレーションの改善

 SSRに関連して、バージョン3.5で導入された仕組みとして、非同期コンポーネントのハイドレーションのタイミングが選択可能になったことがあります。すなわち、クライアント側でいつコンポーネントがレンダリングされるかを選択できるようになったのです。これを、Lazy Hydrationと呼んでいます。例えば、リスト11のようなコードです。

[リスト11]Lazy Hydrationの例
const AsyncRandSection = defineAsyncComponent({
  loader: () => {
    return import("@/components/RandSection.vue");
  },
  hydrate: hydrateOnVisible()  // (1)
});

 Lazy Hydrationを実現する場合は、非同期コンポーネントを定義するdefineAsyncComponent()の引数オブジェクトに、hydrateプロパティを定義することです。このhydrateプロパティの値としては、表1のものが可能です(これ以外に自作も可能)。

表1:hydrateプロパティの値

ハイドレーションのタイミング
hydrateOnIdle() ブラウザがアイドル状態の時
hydrateOnVisible() コンポーネントの要素部分が表示された時
hydrateOnMediaQuery() メディアクエリと一致した時
hydrateOnInteraction() イベントがトリガーされた時

 リスト11では、hydrateOnVisible()を指定しているため、ブラウザをスクロールするなどして、AsyncRandSection部分が表示されるようになった際に、クライアントでレンダリングが実行されるようになります。

カスタム要素の改善

 最後に、カスタム要素に関する改善を簡単に紹介しておきます。カスタム要素は、Vueプロジェクトのみを対象としている場合は、ほとんど不要なものと言えます。一方で、Vueのコンポーネントを、例えばReactなどの他のフレームワークやウェブコンポーネントなどと一緒に使いたい場合に、利用されます。その際利用される関数が、defineCustomElement()です。

 このdefineCustomElement()関数のオプションを指定する第2引数の内容が改善され、これまでのstylesプロパティに加えて、バージョン3.5から表2のプロパティが追加されています。

表2:defineCustomElement()関数のオプションプロパティ
プロパティ 内容
configureApp Vueアプリのインスタンスを設定できる関数
shadowRoot falseを指定することでShadow DOM(※1)を利用せずにカスタム要素が作成できる
nonce styleタグにnonce属性(※2)として追加される

※1:ウェブコンポーネントの仕組みのひとつで、ある要素配下のDOMを、その外部のCSSやJavaScriptの干渉を受けないように隠蔽する方法です。隠蔽するDOMの大元の要素をShadow Host、配下の要素をShadow Treeと言います。

※2:Webページ上に埋め込まれた悪意あるコードが実行されないように付与されたランダムな文字列。HTTPレスポンスヘッダに埋め込まれた値と同じ場合に、正規のコードとみなされます。

 例えば、リスト12のようなカスタム要素を設定すると、vue-rand-section要素はShadow DOMを利用しないコンポーネントとなります。そのため、そのコンポーネントには外部のCSSが適用されるようになります。

[リスト12]Shadow DOMを利用しないカスタムタグの例
const randSection = defineCustomElement(
  RandSection, 
  {shadowRoot: false}
);
customElements.define("vue-rand-section", randSection);

 さらに、カスタム要素から親ホスト要素にアクセスするための表3のヘルパー関数もバージョン3.5で追加されています。

表3:カスタム要素に関してバージョン3.5で追加されたヘルパー関数
関数 内容
useHost() カスタム要素のhostを取得する
useShadowRoot() カスタム要素のshadowRootを取得する
this.$host Options APIでカスタム要素のホスト要素を公開する

終わりに

 Vueのバージョン3.4と3.5の新機能を紹介する本記事は、いかがでしたでしょうか。今後もVueのアップデートに注目していきたいと思います。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
ますます便利になるVue.jsの新機能を探ろう!連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/20458 2024/11/22 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー