JavaScript
vue.js
日本語訳
Macross

Vue.js 2.6がリリースされた

2019/02/05にVue.js 2.6 "Macross"がリリースされました

そのうちもっと適切な日本語訳が出ると思いますが、まだ無いので紹介してみます。

以下はVueの作者Evan Youによる記事、Vue 2.6 releasedの日本語訳です。


Vue 2.6 released

Vueは昨日、5歳の誕生日(Vueniversary)を迎えました。

そして本日、素晴らしいことにVue 2.6 "Macross"の発表を行うことができました。

01.jpeg

この一年、我々は新しいCLIと3.0のプロトタイピングに多大な時間を費やしました。

その結果、Vue2.xはしばらくメジャーアップデートを行えませんでした。

しかし今こそ、その時です。

このリリースには、以下に解説する多数の大幅な改善、内部構造の変更、そして新機能が含まれています。

詳細についてはGitHubのリリースノートも参照してください。


Slots: New Syntax, Performance Improvements & Alignment with 3.0

Slotは、Vueの柔軟なコンポーネント構成を実現する重要なメカニズムです。

3.0のプロトタイピング中に、我々はそれを改善する幾つもの方法を発見しました。

それらのうちのいくつかは破壊的変更を行わずに導入することが可能であったため、2.xのマイナーリリースにおいて導入することになりました。

破壊的変更が必要なものについては、将来的に変更が容易にできるような代替手段を2.xで段階的に提供します。


New Syntax

最初のステップはスコープ付きスロットの新構文です。

我々はいくつもの異なる文法(その1その2その3)を提案し、議論と実験を行い、最終的にはこのRFCに従ったv-slot構文を使用することに決めました。

名前付きスロットを使った簡単な例は以下のとおりです。


gist.github.com/yyx990803/2d8752821c6d658d426c3759180cfc9a#file-slot-example-html

<my-component>

<template v-slot:header>
<p>Header</p>
</template>

<template v-slot:item="{ data }">
<h2>{{ data.title }}</h2>
<p>{{ data.text }}</p>
</template>

<template v-slot:footer>
<p>Footer</p>
</template>
</my-component>


新構文では、これまでのスロットとスコープ付きスロットをひとつの文法に統一し、より明示的でわかりやすい名前付きスロットの使用を強制します。

そしてこれは既存の構文とも完全に互換します。

既存のスロット構文を使い慣れているのであれば、新構文を導入するに至った理論的根拠をよりよく理解するためにRFCを読むことをお勧めします。

まだスロットに慣れていないのであれば、かわりに更新されたドキュメントを読むとよいでしょう。


Performance Improvements

Vue 3.0で導入される予定のスロットのもうひとつの改善点は、スコープ付きスロットのパフォーマンス上の利点を享受するために、通常のスロットとスコープ付きスロットを統合することです。

通常のスロットは、親要素のレンダリング中にレンダリングされます。

スロットの依存関係が変化すると、親コンポーネントと子コンポーネントの両方が再レンダリングされます。

一方スコープ付きスロットはインライン関数にコンパイルされ、子コンポーネントのレンダリングサイクル中に呼び出されます。

スコープ付きスロットによって依存関係が子コンポーネントに限定されるため、より正確な更新が行われることになります。

Vue2.6においては、スコープ付きスロットのみを使用している場合は、親スコープのみに影響を与える変更は親コンポーネントのみを更新し、子コンポーネントを更新しないようにする最適化が導入されました。

追加として、

・新しいv-slot構文は全てスコープ付きスロットにコンパイルされる。これにより新構文を使用したスロットは自動的にパフォーマンスが向上する。

・通常のスロットはthis.$scopedSlots関数として公開される。templatesのかわりにrenderを使っている場合、どのタイプのスロットかを気にせず常にこれを利用できる。

Vue3.0では、スコープ付きスロットと通常スロットの区別はなくなります。

全てのスロットは同じ構文で記述し、同じ結果にコンパイルされ、同じパフォーマンスを持ちます。


Async Error Handling

Vueの組み込みエラー処理メカニズム(コンポーネント内のerrorCapturedフックとグローバルのerrorHandlerフック)は、いずれもv-onハンドラ内のエラーをキャッチするようになりました。

またライフサイクルフックやイベントハンドラが非同期処理を実行した際、Promiseチェーンがキャッチしないエラーをエラーハンドラに渡せるように、Promiseをreturnすることができるようになりました。

asyncは暗黙にPromiseを返すので、async/awaitを使用している場合はさらに簡単に書けます。


gist.github.com/yyx990803/88a0a432796f14745ade92757e71ba33#file-async-error-js

export default {

async mounted() {
// if an async error is thrown here, it now will get
// caught by errorCaptured and Vue.config.errorHandler
this.posts = await api.getPosts()
}
}


Dynamic Directive Arguments

Directiveに動的な引数を書けるようになります。


gist.github.com/yyx990803/bf1cf3116b365cc581d2ad51906c4f3d#file-dynamic-directive-argument-html

<div v-bind:[attr]="value"></div>

<div :[attr]="value"></div>

<button v-on:[event]="handler"></button>
<button @[event]="handler"></button>

<my-component>
<template v-slot:[slotName]>
Dynamic slot name
</template>
</my-component>


より詳細な解説はこのRFCにあります。

便利な使い方として、引数にnullを入れるとバインドやリスナーが削除されます。


ライブラリ作者への注意:この機能はVueランタイム2.6.0以上を要求します。コンパイル済バージョンを配布する場合、2.6以前と互換が必要であればこの機能を使用しないでください。



Code Frame in Compiler Warning Messages

2.6以降、テンプレートコンパイル時の警告のほとんどに、対象ソースコードの情報が含まれるようになりました。

@gzzhanghaoプルリクのおかげです。

これらの警告に対して適切な情報が表示されるようになります。

02.png


Explicit Creation of Standalone Reactive Objects

Vue2.6では、スタンドアロンなリアクティブオブジェクトを作成する、明示的なグローバルAPIが導入されました。


gist.github.com/yyx990803/799afa227996a59999e32d8a0a856852#file-observable-js

const reactiveState = Vue.observable({

count: 0
})

このオブジェクトは算出プロパティやrender関数で直接使用することができ、そして値が変更された場合は適切な更新が行われます。


Data Pre-fetching during Server Side Rendering

serverPrefetchフックは、サーバサイドレンダリングの最中に、任意のコンポーネントのデータをプリフェッチすることができます。

SSRのより柔軟な使い方を可能にし、fetchとrouter間の無駄なデータのやりとりを減少させます。

Nuxtvue-apolloといったライブラリは、この新機能を使って実装を単純化する計画を既に始めています。


ES Module Build for Direct Import

これまでのES Moduleは、主にバンドラでの使用を想定していました。

これらは環境変数をコンパイル時に置き換えて使用することを想定しています。

Vue2.6では、ブラウザ内で直接使用するためのES Moduleも提供されます。


gist.github.com/yyx990803/f5e26b97ae74ae04d1480e4f1ec1fb47#file-esm-html

<script type="module">

import Vue from 'https://unpkg.com/vue/dist/vue.esm.browser.js'

new Vue({
// ...
})
</script>



Important Internal Changes


Reverting nextTick to Microtask

v-onイベントハンドラで更新が発生した場合、nextTickは元々microTimerFuncを使って更新をキューに入れていましたが、Vue2.5.0においてmacroTimerFuncを使うように内部的変更が行われました。

これはいくつかのブラウザに置いて発生するエッジケースの問題に対応するためのものだったのですが、しかしこれは他の多くの問題を引き起こしました。

また元の問題に対しては、別のよりよい解決策を発見できました。

そのため、Vue2.6では変更を元に戻し、常にmicroTimerFuncを使用するようになっています。

より具体的な内容に興味があるなら、こちらを参照してください。


Functions on this.$scopedSlots now always return Arrays

この項目はrenderを使っているユーザにのみ影響があります。

スコープ付きスロットはrender関数内にthis.$scopedSlotsとして公開されます。

これまではスコープ付きスロット関数は、親コンポーネントに応じて、単体のVNodeか、VNodeの配列が返ってきていました。

返り値の型が不明瞭になり、意図しない問題が発生する可能性がありました。

Vue2.6では、この関数はVNodeの配列もしくはundefinedいずれかを返すようになりました。

返り値の型を適切に判定していない場合、既存のコードに影響が発生する可能性があります。

詳細はこちら


Shoutouts

プルリクを提供してくれたコントリビュータ、そしてRFCの議論に参加してくれた全てのコミュニティメンバーに感謝します。


コメント欄

「Vueはアプデされるたびに、開発者の負担を和らげる新たな便利さがもたらされる。Vue万歳!」

「この新文法は、複雑な問題に対する最もスマートな解決策だ。」

「『SSR中のデータプリフェッチ』『コンパイラ警告のソースコード表示』私にとっての神機能だ。早すぎるクリスマスプレゼントありがとう。」

「ES Moduleのインポートについて質問。もしかして今後、これを使ってCDNをLazyLoadできるようになったりする?」

「sublime」


感想

いったい何処がどうMacrossなのだろう。

Vue3.0リリースに向けての新機能のうち、互換を壊さない部分を先行して持ってきたかんじでしょうか。

serverPrefetchとかすごい使えそうですね。

全く関係ないがサーバサイドレンダリングをSSRと略されると一瞬びくっとしてしまう。