vue.js

[和訳] 次期 Vue (v3.0) の計画 / Plans for the Next Iteration of Vue.js

ありがとう Evan You, ありがとう Vue.js 開発チーム

元記事
Plans for the Next Iteration of Vue.js – The Vue Point – Medium

Plans for the Next Iteration of Vue.js ─ Vue.js における次のイテレーションの計画

先週の Vue.js London で、私は Vue の次のメジャーバージョンについて簡単なプレビューを行った。このポストでは、計画の詳細な概要を提供する。

Last week at Vue.js London I gave a brief sneak peek of what’s coming in the next major version of Vue. This post provides an in-depth overview of the plan.

なぜ新しいメジャーバージョンを? / Why a new major version?

Vue 2.0 はちょうど2年前にリリースされた(時が経つのは早いものだ!)。この期間中、core は下位互換性を維持しながら5つのマイナーリリースを行った。他にも改善をもたらすアイデアはあったが、それらは破壊的な変更を伴うために、延期されてきた。同時に、JavaScript エコシステムと言語そのものが急速に進化している。ワークフローを強化するツールが大きく改善されたこと、また多くの新しい言語機能によって、Vue が対処しようとしている問題を、より簡単・完全・効率的に解決できるようになった。エキサイティングなのは、ES2015 が主要なブラウザでサポートされるようになることだ。Vue 3.0 は、これらの新しい言語機能を活用して、Vue コアの小型化、高速化、および強力化を目指している。

Vue 2.0 was released exactly two years ago (how time flies!). During this period, the core has remained backwards compatible with five minor releases. We’ve accumulated a number of ideas that would bring improvements, but they were held off because they would result in breaking changes. At the same time, the JavaScript ecosystem and the language itself has been evolving rapidly. There are greatly improved tools that could enhance our workflow, and many new language features that could unlock simpler, more complete, and more efficient solutions to the problems Vue is trying to solve. What’s more exciting is that we are seeing ES2015 support becoming a baseline for all major evergreen browsers. Vue 3.0 aims to leverage these new language features to make Vue core smaller, faster, and more powerful.

Vue 3.0 は現在プロトタイプ段階にあり、私たちは既に 2.x で機能的に近いランタイムを実装している。下記の項目の多くはすでに実装されているか、実行可能であることが確認されている。未だ実施されていないか、検討段階にあるものには*印がついている。

Vue 3.0 is currently in prototyping phase, and we have already implemented a runtime close to feature-parity with 2.x. Many of the items listed below are either already implemented, or confirmed to be feasible. Ones that are not yet implemented or still in exploration phase are marked with a *.

詳細 / The Details

高レベルAPIの変更 / High-Level API Changes

TL;DR: render function API と scoped-slots syntax を除き、その全てが互換性を維持されているか、2.x 互換にすることができる。

TL;DR: Everything except render function API and scoped-slots syntax will either remain the same or can be made 2.x compatible via a compatibility build.

これは新しいメジャーバージョンであるため、いくつかの破壊的な変更が起こるだろう。しかし、私たちは下位互換性を真剣に受け止めているので、なるべく早くこれらの変更についてお知らせしたい。現在計画されている public API の変更点は次のとおり。

Since it’s a new major, there is going to be some breaking changes. However, we take backwards compatibility seriously, so we want to start communicating these changes as soon as possible. Here’s the currently planned public API changes:

  • テンプレートの構文は 99% 今まで通りである。scoped-slots syntax には微妙な微調整があるかもしれないが、それ以外にテンプレートの変更は計画されていない。

    • Template syntax will remain 99% the same. There may be small tweaks in scoped slots syntax, but other than that we have no plans to change anything else for templates.
  • 3.0 は、あらゆる transpilation や stage-x features を必要とせずに、ネイティブ ES2015 で快適に使用できる API を提供することを目的として、クラスベースのコンポーネントをネイティブにサポートする。現在のほとんどのオプションは、クラスベースの API に妥当にマッピングされる。class fields や decorator などの stage-x features は、記述体験を向上させるためにオプションとして使用できるようになる。さらに、API は TypeScript 型推論を考慮して設計される。3.x コードベースそのものも TypeScript で記述され、改良されたTypeScript サポートが適用される。(とはいえ、アプリケーションで TypeScript を使用することは完全に任意である)

    • 3.0 will support class-based components natively, with the aim to provide an API that is pleasant to use in native ES2015 without requiring any transpilation or stage-x features. Most current options will have a reasonable mapping in the class-based API. Stage-x features such as class fields and decorators can still be used optionally to enhance the authoring experience. In addition, the API is designed with TypeScript type inference in mind. The 3.x codebase will itself be written in TypeScript, and providing improved TypeScript support. (That said, usage of TypeScript in an application is still entirely optional.)
  • 2.x のオブジェクトベースのコンポーネントは、内部的なクラスベースへの変換を通じて引き続き利用可能である。

    • The 2.x object-based component format will still be supported by internally transforming the object to a corresponding class.
  • Mixins はサポートされ続ける。 *

    • Mixins will still be supported.*
  • トップレベル API が大幅に見直され、プラグインのインストール時に Vue ランタイムをグローバルに変更しなくなる代わりに、プラグインはコンポーネントツリーに対して適用 (applied and scoped) される。これにより、特定のプラグインに依存するコンポーネントのテストが容易になるほか、異なるプラグインを扱う複数の Vue アプリケーションを1つのページにマウントすることが単一の Vue ランタイムで可能になる。*

    • Top level APIs will likely receive an overhaul to avoid globally mutating the Vue runtime when installing plugins. Instead, plugins will be applied and scoped to a component tree. This will make it easier to test components that rely on specific plugins, and also make it possible to mount multiple Vue applications on the same page with different plugins, but using the same Vue runtime.*
  • 関数型コンポーネントは遂に単なる関数になる。ただし、非同期コンポーネントに関してはヘルパ関数を使って明示的に作成する必要がある。

    • Functional components can finally be plain functions —however, async components will now need to be explicitly created via a helper function.
  • 最も多くの変更を受ける部分は、render 関数の中で使われる Virtual DOM のフォーマットである。私たちは現在、主要なライブラリ作者からのフィードバックを集めており、変更内容が確固たるものになり次第詳細を共有するが、あなたが手書きの (JSX でない) render 関数に大きく依存していない限りは、そこそこ明快にアップグレードできるはずだと考えている。

    • The part that will receive the most changes is the Virtual DOM format used in render functions. We are currently collecting feedback from major library authors and will be sharing more details as we are more confident of the changes, but as long as you don’t heavily rely on hand-written (non-JSX) render functions in your app, upgrading should be a reasonably straightforward process.

ソースコードアーキテクチャ / Source Code Architecture

TL;DR: より良く分離された内部モジュール、TypeScript、よりコントリビューションしやすくなるコードベース。

TL;DR: better decoupled internal modules, TypeScript, and a codebase that is easier to contribute to.

よりクリーンでメンテナブルなアーキテクチャのために、私たちは 3.0 を最初から書き直している。特に、よりコントリビューションしやすくなることを心がけている。また複雑さのスコープを分割するため、いくつかの内部機能を個々のパッケージへと切り出している。たとえば、observer モジュールは独自のパブリック API とテストを持つ独自のパッケージになる。しかしこれらは、framework-level-API には影響しない。Vue を使用するために個々のパッケージをいちいちインポートする必要もなく、最終的な Vue のパッケージがそれらの内部パッケージを使って組み立てられるようになる。

We are re-writing 3.0 from the ground up for a cleaner and more maintainable architecture, in particular trying to make it easier to contribute to. We are breaking some internal functionalities into individual packages in order to isolate the scope of complexity. For example, the observer module will become its own package, with its own public API and tests. Note this does not affect framework-level API— you will not have to manually import individual bits from multiple packages in order to use Vue. Instead, the final Vue package is assembled using these internal packages.

コードベースも TypeScript で書かれている。これは新しいコードベースにコントリビューションするために TypeScript の熟練が必要になることを意味するが、型情報と IDE のサポートにより、新しいコントリビューターがより簡単に有意義なコントリビューションができるようになると確信している。

The codebase is also now written in TypeScript. Although this will make proficiency in TypeScript a pre-requisite for contributing to the new codebase, we believe the type information and IDE support will actually make it easier for a new contributor to make meaningful contributions.

observer と scheduler を個別のパッケージに分離することで、これらの部分の代替の実装を簡単に試すことができるようになる。たとえば IE11 互換の observer 実装を同じ API で実装できるし、requestIdleCallback を使って時間のかかる処理を行う代替スケジューラを実装することもできる。

Decoupling the observer and scheduler into separate packages also allows us to easily experiment with alternative implementations of these parts. For example, we can implement an IE11 compatible observer implementation with the same API, or an alternative scheduler that leverages requestIdleCallback to yield to the browser during long updates.*


新しいソースコード構造をチラ見せ (変わるかも) / Sneak peek of the new source code structure (subject to change)

監視メカニズム / Observation Mechanism

TL;DR: より完全・正確・効率的・デバッグ可能なリアクティブトラッキングおよび observables を作成するための API

TL;DR: more complete, precise, efficient and debuggable reactivity tracking & API for creating observables.

3.0 には Proxy ベースの observer 実装が付属している。これは完全な言語カバレッジを持つリアクティブトラッキングを提供する。これにより、Object.defineProperty に基づいた Vue 2 の現在の実装における多くの制限が解消される:

3.0 will ship with a Proxy-based observer implementation that provides reactivity tracking with full language coverage. This eliminates a number of limitations of Vue 2’s current implementation based on Object.defineProperty:

  • プロパティの追加 / 削除の検出

    • Detection of property addition / deletion
  • Array のインデックスの変更 / .length の変化の検出

    • Detection of Array index mutation / .length mutation
  • Map, Set, WeakMap, WeakSet のサポート

    • Support for Map, Set, WeakMap and WeakSet

新しい observer には以下の機能もある:

The new observer also features the following:

  • observables を作成するための公開 API。これにより、中小規模のシナリオに対応する、軽量でシンプルなクロスコンポーネント状態管理ソリューションが提供される。

    • Exposed API for creating observables. This offers a light-weight, dead simple cross-component state management solution for small to medium scale scenarios.
  • Lazy Observation がデフォルトになる。2.x ではあらゆるリアクティブなデータが、その大小に関係なく、起動時に observe されていた。データセットが巨大であれば、アプリの起動に顕著なオーバーヘッドを引き起こす可能性がある。3.x では、アプリケーションの最初に表示される部分をレンダリングするために使用されるデータだけが observe されるようになり、もちろん observation 自体もより高速になる。

    • Lazy observation by default. In 2.x, any reactive data, regardless of how big it is, will be observed on startup. This can cause a noticeable overhead on app startup if your dataset is huge. In 3.x, only data used to render the initially visible part of your app will need to be observed, not to mention the observation itself is also much faster.
  • より正確な変更通知。例: 2.x では、Vue.set を使って強制的に新しいプロパティを追加すると、そのオブジェクトに依存するあらゆるウォッチャが再評価される原因となる。3.x では、特定のプロパティに依存するウォッチャにのみ通知されるようになる。

    • More precise change notification. An example: in 2.x, force adding a new property using Vue.set will cause any watcher that depends on the object to re-evaluate. In 3.x, only watchers that relies on that specific property will be notified.
  • Immutable observables: ネストされたプロパティにおいても不変な値が作成可能になる。それは内部的に、一時的にアンロックされる場合を除いて変更できない。このメカニズムは、渡された props を凍結したり、Vuex ステートツリーを mutation の外から変更できないようにするために使える。

    • Immutable observables: we can create “immutable” versions of a value that prevents mutations even on nested properties, except when the system temporarily unlocks it internally. This mechanism can be used to freeze passed-down props or Vuex state trees outside mutations.
  • より良いデバッグ機能: 新しい renderTracked フックと renderTriggered フックを使用して、コンポーネントの再レンダリングがいつ、なぜ track / trigger されるかをより正確にトレースすることができるようになる:

    • Better debugging capabilities: we can precisely trace when and why a component re-render is tracked or triggered using the new renderTracked and renderTriggered hooks:


なぜコンポーネントが再レンダリングされるのかを簡単に理解する / Easily understand why a component is re-rendering

その他のランタイムの改善 / Other Runtime Improvements

TL;DR: より小さく、速く、tree-shakable な機能、Fragment と Portal、カスタムレンダラー API。

TL;DR: smaller, faster, tree-shakable features, fragments & portals, custom renderer API.

  • より小さい: 新しいコードベースは、基本的に tree-shaking と相性が良いように設計されている。組み込みコンポーネント (<transition>, <keep-alive>) やディレクティブランタイムヘルパ (v-model) のような機能はオンデマンドに tree-shaking 可能にインポートされるようになった。新しいランタイムのサイズは基本的に <10kb gzipped である。 加えて、tree-shaking 可能であることにより、今後は使用しないユーザにペイロードのペナルティを課すことなく、より多くの組み込み機能を提供できる。

    • Smaller: the new codebase is designed from the ground up to be tree-shaking friendly. Features such as built-in components (<transition>, <keep-alive>) and directive runtime helpers (v-model) are now imported on-demand and tree-shakable. The constant baseline size for the new runtime is <10kb gzipped. In addition, features being tree-shakable also allows us to offer more built-in features down the road without incurring payload penalties for users that don’t use them.
  • より速い: 事前のベンチマークでは、raw Virtual DOM のマウント & パッチ (私たちは最速の Virtual DOM 実装である Inferno から多くのトリックを学んだ), コンポーネントインスタンスの初期化とデータの observation を含み、全面的に最大で 100% のパフォーマンス向上が見られている。3.0は、あなたのアプリが起動したときに JavaScript で費やされた時間の半分を削減する。

    • Faster: on preliminary benchmarks, we are seeing up to 100% performance improvement across the board, including raw Virtual DOM mounting & patching (we learned quite a few tricks from Inferno, the fastest Virtual DOM implementation out there), component instance initialization and data observation. 3.0 will shave off half the time spent in JavaScript when your app boots up.
  • Fragment と Portal: そのサイズが縮小されたにもかかわらず、3.0には、Fragment(複数のルートノードを返すコンポーネント)と Portal(コンポーネント内ではなく DOM の別の部分にサブツリーをレンダリングする)の組み込みサポートが付属する。

    • Fragments & Portals: despite the size reduction, 3.0 comes with built-in support for Fragments (component returning multiple root nodes) and Portals (rendering a sub-tree in another part of the DOM, instead of inside the component).
  • 改善された slot のメカニズム: コンパイラによって生成されたすべての slot は、子コンポーネントの render 呼び出し中に関数として呼び出されるようになる。これにより、slot の依存関係が親ではなく子の依存関係になることが保証される。これは、次のことを意味する。1. slot の内容が変更された場合、子のみが再レンダリングされる。2. 親を再レンダリングしても、その slot の内容が変更されなければ、子は再レンダリングする必要はない。この変更により、コンポーネントツリーレベルでより正確な変更の検出が提供されるため、無駄な再レンダリングはさらに少なくなった!

    • Improved slots mechanism: All compiler-generated slots are now functions and invoked during the child component’s render call. This ensures dependencies in slots are collected as dependencies for the child instead of the parent. This means that: 1. when slot content changes, only the child re-renders; 2. when the parent re-renders, the child does not have to if its slot content did not change. This change offers even more precise change detection at the component tree level, so even fewer useless re-renders!
  • カスタムレンダラー API: カスタムレンダラーを作成するためのファーストクラス API が利用可能になり、それらの改変のために Vue コードベースをフォークする必要はなくなった。これにより、WeexNativeScript-Vue などの render-to-native プロジェクトがアップストリームの変更を最新の状態に保ちやすくなる。また、さまざまな目的のためにカスタムレンダラを作成することが簡単になる。

    • Custom Renderer API: a first-class API for creating custom renderers will be available, and no longer requires forking the Vue codebase with custom modifications. This will make it much easier for render-to-native projects like Weex and NativeScript Vue to stay up-to-date with upstream changes. It would also make it trivially easy to create custom renderers for various other purposes.

コンパイラの改良* / Compiler Improvements*

TL;DR: tree-shaking と相性の良い出力、さらなる AOT 最適化、より良いエラー情報とソースマップをサポートしたパーサ。

TL;DR: tree-shaking friendly output, more AOT optimizations, parser with better error info and source map support.

  • tree-shaking-capable なバンドラを対象とし、テンプレートはオプション機能をインポートするために ES modules syntax を利用するようになる。これにより、未使用のオプション機能は、最終的なバンドルから削除される。

    • When targeting tree-shaking-capable bundlers, templates that make use of optional features will generate code that imports those features using ES modules syntax. Unused optional features are thus dropped from the final bundle.
  • 新しい Virtual DOM 実装の改善により、より効果的なコンパイル時の最適化も実行できる。

    • static tree hoisting
    • static props hoisting
    • compiler-hints for runtime to skip children normalization
    • VNode creation fast paths
    • etc...
  • Due to improvements in the new Virtual DOM implementation, we are also able to perform more effective compile-time optimizations such as static tree hoisting, static props hoisting, compiler-hints for runtime to skip children normalization, VNode creation fast paths, etc…
  • テンプレートのコンパイルエラーで位置情報を提供するためにパーサを書き直す予定がある。これは、テンプレートのソースマップのサポートにもつながるはずである。新しいパーサは、eslint-plugin-vue や IDE 言語サービスなど、サードパーティツールとのインテグレーションの基礎となる。
  • We plan to rewrite the parser to provide location information in template compilation errors. This should also lead to template source map support, and the new parser can serve as the foundation for 3rd party tooling integration, such as eslint-plugin-vue and IDE language services.

IE11 サポート* / IE11 Support*

TL;DR: サポートされる予定だが、Vue 2.x と同じリアクティブ制限を持つ別のビルドになる。

TL;DR: it will be supported, but in a separate build with the same reactivity limitations of Vue 2.x.

新しいコードベースは現在主要ブラウザのみを対象としており、ネイティブ ES2015 サポートを基本的な前提としている。しかし、悲しいかな、われわれは多くのユーザがもうしばらく IE11 をサポートする必要があることを知っている。ES2015 のほとんどの機能は、Proxy を除いて、IE11 用にトランスパイル/ポリフィルすることができるため、同一の API で、古い ES5 の Object.defineProperty API を使用して代替 observer を実装する予定である。この observer 実装を使用して、Vue 3.x の別のビルドが配布されるが、このビルドは、Vue 2.x の同じ変更検出に関する注意事項の対象となるため、3.x の "modern" ビルドと完全には互換性がない。これは2つの異なるビルドの互換性を認識する必要性に繋がり、これらがライブラリ作者にいくらかの不便を与えることを私たちは認識しているが、このステージに差し掛かった際には、明確なガイドラインを提供することを約束する。

The new codebase currently targets evergreen browsers only and assumes baseline native ES2015 support. But alas, we know a lot of our users still need to support IE11 for the foreseeable future. Most of the ES2015 features used can be transpiled / polyfilled for IE11, with the exception for Proxies. Our plan is to implement an alternative observer with the same API, but using the good old ES5 Object.defineProperty API. A separate build of Vue 3.x will be distributed using this observer implementation. However, this build will be subject to the same change detection caveats of Vue 2.x and thus not fully compatible with the “modern” build of 3.x. We are aware that this imposes some inconvenience for library authors as they will need to be aware of compatibility for two different builds, but we will make sure to provide clear guidelines on this when we reach that stage.

どのように到達するか / How Do We Get There

まず第一に、今日 (訳注: 2018/9/30) このような発表を行ったが、明確なタイムラインは未だ存在しない。現時点で私たちが知っていることは、そこに到達するために取るべきステップである。

First of all, although we are announcing it today, we do not have a definitive timeline yet. What we do know at the moment is the steps we will be taking to get there:

1. ランタイム・プロトタイプの内部フィードバック / Internal Feedback for the Runtime Prototype

これが現在のフェーズである。すでに、新しい observer、 Virtual DOM およびコンポーネント実装を含む、動作中のランタイム・プロトタイプが用意されている。私たちは、影響力のあるコミュニティプロジェクトの著者のグループを招いて、内部的な変更をフィードバックしてもらい、それらが快適であることをあらかじめ確認したいと思っている。私たちは、3.0 と重要なライブラリが同時にリリースされ、それらのプロジェクトに頼っているユーザが簡単にアップグレードできることを保証したい。

This is the phase we are in right now. Currently, we already have a working runtime prototype that includes the new observer, Virtual DOM and component implementation. We have invited a group of authors of influential community projects to provide feedback for the internal changes, and would like to make sure they are comfortable with the changes before moving forward. We want to ensure that important libraries in the ecosystem will be ready at the same time when we release 3.0, so that users relying on those projects can upgrade easily.

2. RFC を通じた公開フィードバック / Public Feedback via RFCs

新しいデザインに一定のレベルの信頼を得たら、破壊的な変更ごとに下記を含む専用の RFC issue を開くだろう:

Once we gain a certain level of confidence in the new design, for each breaking change we will be opening a dedicated RFC issue which includes:

  • 影響範囲

    • Scope of the change;
  • 変更の根拠: 私たちは何を得て、どのようなトレードオフが行われているのか

    • Reasoning behind the change: what do we gain, and what tradeoffs are being made;
  • アップグレードパス:完全に下位互換性のあるやり方で、リムーバブルな互換レイヤー経由で、あるいは codemods 経由で導入できるか?

    • Upgrade path: can it be introduced in a completely backwards-compatible fashion, via a removable compatibility layer, or via codemods?

これらのアイデアをまとめるために、より広範なコミュニティからのフィードバックを期待している。

We will anticipate public feedback from the wider community to help us consolidate these ideas.

3. 2.x2.x-nextに互換機能を導入する / Introduce Compatible Features in 2.x & 2.x-next

2.x のことも忘れないよ! 私たちは実際には、2.x を使用してユーザに新しい変更を徐々に習得させる予定だ。API の変更を opt-in アダプタによって 2.x に徐々に導入し、2.x-next で新しい Proxy ベースの observer を試すことができる。

We are not forgetting about 2.x! In fact, we plan to use 2.x to progressively accustom users to the new changes. We will be gradually introducing confirmed API changes into 2.x via opt-in adaptors, and 2.x-next will allow users to try out the new Proxy-based observer.

2.x の最後のマイナーリリースは LTS になり、3.0 がリリースされても 18 ヶ月間にわたりバグとセキュリティ修正を受け続ける。

The last minor release in 2.x will become LTS and continue to receive bug and security fixes for 18 months when 3.0 is released.

4. アルファ版 / Alpha Phase

3.0 のコンパイラとサーバーサイド・レンダリングを完成させたら、アルファ版の作成を開始する。これらは主に、小さなグリーンフィールドの (訳注: まっさらな状態から作り始める) アプリの安定性テストの目的に使用される。

Next, we will finish up the compiler and server-side rendering parts of 3.0 and start making alpha releases. These will mostly be for stability testing purposes in small greenfield apps.

5. ベータ版 / Beta Phase

ベータ段階では、Vue Router、Vuex、Vue CLI、Vue DevTools などのサポートライブラリとツールを更新して、新しいコアで円滑に動作するようにする。私たちはコミュニティの主要なライブラリ作者と協力して、彼らが 3.0 の準備を整えるのを手伝っていく。

During beta phase, our main goal is updating support libraries and tools like Vue Router, Vuex, Vue CLI, Vue DevTools and make sure they work smoothly with the new core. We will also be working with major library authors from the community to help them get ready for 3.0.

6. RC版 / RC Phase

API とコードベースが安定しているとみなしたら、API のフリーズを経て RC フェーズに入る。このフェーズでは、2.x API の互換レイヤーを含む 3.0 のビルドである "compat build" に取り組む。このビルドには、アプリでの 2.x API の使用に関する deprecation warnings を表示するためのフラグを付けることもできる。compat build は、アプリを 3.0 にアップグレードするためのガイドとして使用できる。

Once we consider the API and codebase stable, we will enter RC phase with API freeze. During this phase we will also work on a “compat build”: a build of 3.0 that includes compatibility layers for 2.x API. This build will also ship with a flag you can turn on to emit deprecation warnings for 2.x API usage in your app. The compat build can be used as a guide to upgrade your app to 3.0.

7. IE11 ビルド / IE11 build

最終リリース前の最後のタスクは、上記の IE11 互換ビルドとなる。

The last task before the final release will be the IE11 compatibility build as mentioned above.

8. 最終リリース / Final Release

正直に言うと、これがいつになるかはまだ分からないが、たぶん2019年内ではあるね。また、特定の日付を決めるよりも、堅実で安定したものを届けることを重要視している。やるべきことは山積みだが、私たちは次に来るものに興奮しているよ!

In all honestly, we don’t know when this will happen yet, but likely in 2019. Again, we care more about shipping something that is solid and stable rather than hitting specific dates. There is a lot of work to be done, but we are excited for what’s coming next!