原文標(biāo)題: The process: Making Vue 3
作者: 尤雨溪 Evan You (Vue.js 作者)
原文鏈接: https://increment.com/frontend/making-vue-3/
Over the past year, the Vue team has been working on the next major version of Vue.js, which we hope to release in the first half of 2020. (This work is ongoing at the time of writing.) The idea for a new major version of Vue took shape in late 2018, when the codebase of Vue 2 was about two-and-a-half years old. That may not sound like a long time in the life span of generic software, but the frontend landscape had changed drastically during that period.
Two key considerations led us to the new major version (and rewrite) of Vue: First, the general availability of new JavaScript language features in mainstream browsers. Second, design and architectural issues in the current codebase that had been exposed over time.
在過去的一年里,Vue 團(tuán)隊(duì)一直在開發(fā)下一個大版本的 Vue.js (即 Vue 3.0)登颓,預(yù)期在 2020 上半年發(fā)布(在撰寫本文時简十,這項(xiàng)工作仍在進(jìn)行當(dāng)中)缝左。關(guān)于新的 Vue 大版本的構(gòu)想形成于 2018 年底臂痕,當(dāng)時 Vue 2 的代碼庫大約有兩年半的歷史娘香。兩年半對于一般軟件的生命周期來說盈包,可能不算是很長的時間楚里,但在這段時間里匀泊,前端環(huán)境發(fā)生了巨大的變化优训。
有兩個關(guān)鍵的考慮因素催生了新版本的 Vue :一是主流瀏覽器中 JavaScript 語言新特性的普遍可用性。二是當(dāng)前代碼庫中(指 Vue 2.0)隨著時間推移暴露出的一些在設(shè)計和架構(gòu)方面存在的問題各聘。
為何要重寫
利用語言的新特性
With the standardization of ES2015, JavaScript—formally known as ECMAScript, abbreviated to ES—received major improvements, and mainstream browsers were finally starting to provide decent support for these new additions. Some in particular presented opportunities for us to greatly improve Vue’s capabilities.
The most noteworthy among them is Proxy, which allows the framework to intercept operations on objects. A core feature of Vue is the ability to listen to changes made to the user-defined state and reactively update the DOM. Vue 2 implements this reactivity by replacing the properties on state objects with getters and setters. Switching to Proxy would allow us to eliminate Vue’s existing limitations, such as the inability to detect new property additions, and provide better performance.
However, Proxy is a native language feature that cannot be fully polyfilled in legacy browsers. In order to leverage it, we knew we’d have to adjust the framework’s browser support range—a big breaking change that could only be shipped in a new major version.
隨著 ES2015 (ES6) 的標(biāo)準(zhǔn)化揣非,JavaScript(ECMAScript)的能力得到了很大的增強(qiáng),主流的瀏覽器終于開始支持 ES 新特性躲因。而其中一些特性使我們得以有機(jī)會極大提升 Vue 的性能早敬。其中最值得注意的是 Proxy 忌傻,它允許框架攔截對對象的操作。 Vue 的一個核心特性是能夠監(jiān)聽開發(fā)者定義的狀態(tài)(即你經(jīng)常寫的 data 搞监、 pros 和 computed水孩,統(tǒng)稱為用戶狀態(tài))的改變,并且響應(yīng)式更新 DOM 腺逛。Vue 2 通過用 Object.defineProperty 中傳入的 getter 和 setter 方法重載狀態(tài)的屬性改變來實(shí)現(xiàn)響應(yīng)式更新荷愕。切換到 Proxy 能讓我們突破 Vue 原有的響應(yīng)式實(shí)現(xiàn)限制,例如無法檢測新的屬性添加棍矛,并且性能也會更好安疗。然而 Proxy 沒有辦法在過時瀏覽器(IE,說的就是你)中能夠被完全 polyfill (即用舊代碼實(shí)現(xiàn)新特性的兼容)够委。這一點(diǎn)經(jīng)過我們的再三權(quán)衡后決定收窄瀏覽器支持范圍荐类,這種破壞性改動只能在下一個大版本中發(fā)布。
解決架構(gòu)問題
Over the course of maintaining Vue 2, we’ve accumulated a number of issues that have been difficult to address due to the limitations of the existing architecture. For example, the template compiler was written in a way that makes proper source-map support very challenging. Also, while Vue 2 technically enables building higher-level renderers that target non-DOM platforms, we had to fork the codebase and duplicate lots of code in order to make this possible. Fixing these issues in the current codebase would require huge, risky refactors that are almost equivalent to a rewrite.
At the same time, we’ve accumulated technical debt in the form of implicit coupling between the internals of various modules and floating code that doesn’t seem to belong anywhere. This made it harder to understand a part of the codebase in isolation, and we noticed that contributors rarely felt confident making nontrivial changes. The rewrite would give us the opportunity to rethink the code organization with these things in mind.
在維護(hù) Vue 2 的過程中茁帽,因?yàn)楝F(xiàn)有架構(gòu)的局限性玉罐,我們積攢了很多難以解決的問題。比如 template compiler (Vue 的模板編譯器)對于 source-map 的支持成本有點(diǎn)高潘拨。再者吊输,Vue2 為了實(shí)現(xiàn)針對非 DOM 端(如 mpvue 、weex)啟用構(gòu)建高階渲染器(renderer 指實(shí)現(xiàn)渲染相關(guān)的代碼铁追,下同)這一功能季蚂,我們不得不把代碼整個 fork 出來,還留了許多重復(fù)代碼琅束。在當(dāng)前的代碼中修復(fù)這些問題需要大量且高風(fēng)險的重構(gòu)扭屁,等于重寫這個框架。同時也欠下了許多技術(shù)債涩禀,主要表現(xiàn)在框架內(nèi)部各個地方出現(xiàn)的一些隱式耦合的料滥、難以歸類于某個模塊的搖擺代碼,造成代碼的許多獨(dú)立的部分理解起來變得更加困難艾船,貢獻(xiàn)代碼的人們很少能夠自信地提供一些有重要的改動葵腹。這次重寫能讓我們抓住機(jī)會重新反思了代碼組織方式。
原型設(shè)計階段
We started prototyping Vue 3 in late 2018 with the preliminary goal of validating the solutions to these problems. During this stage, we mostly focused on building a solid foundation for further development.
為了初步驗(yàn)證解決方案丽声,我們在 18 年末開始 Vue 3 的原型設(shè)計礁蔗。在這一階段我們主要集中精力在為將來開發(fā)打下堅實(shí)基礎(chǔ)上。
轉(zhuǎn)用 Typescript
Vue 2 was originally written in plain ES. Shortly after the prototyping stage, we realized that a type system would be very helpful for a project of this magnitude. Type checks greatly reduce the chance of introducing unintended bugs during refactors and help contributors be more confident in making nontrivial changes. We adopted Facebook’s Flow type checker because it can be gradually added to an existing plain-ES project. Flow helped to a certain extent, but we didn’t benefit from it as much as we’d hoped; in particular, the constant breaking changes made upgrading a pain. The support for integrated development environments was also not ideal compared to TypeScript’s deep integration with Visual Studio Code.
We also noticed that users were increasingly using Vue and TypeScript together. To support their use cases, we had to author and maintain the TypeScript declarations separately from the source code, which used a different type system. Switching to TypeScript would allow us to automatically generate the declaration files, alleviating the maintenance burden.
Vue 2 使用原生 ES編寫雁社。在原型設(shè)計階段過后 不久浴井,我們意識到類型系統(tǒng)能對于大規(guī)模的項(xiàng)目非常有利。類型檢查能最大程度減少在重構(gòu)過程中或者開源貢獻(xiàn)者貢獻(xiàn)重要改動時產(chǎn)生意外的 bug霉撵。我們之前采用的是 Flow磺浙,因?yàn)樗軌驖u進(jìn)地在原生 ES 項(xiàng)目中引入洪囤。 Flow 確實(shí)有一定程度的幫助,但契合度也沒能達(dá)到我們的期望撕氧。尤其是不斷的破壞性改動使升級成為一種痛苦瘤缩。拿 TypeScript 與 VSCode 的深度集成相比,F(xiàn)low 對 IDE 的支持也不理想伦泥。我們也注意到越來越多的開發(fā)者使用 Vue 與 TS 相結(jié)合剥啤。為了滿足他們的場景,我們需要開發(fā)和維護(hù)一套獨(dú)立于源碼的 TypeScript 聲明文件不脯,而轉(zhuǎn)用 TypeScript 允許我們自動生成聲明文件府怯,減少維護(hù)成本。
解耦內(nèi)部模塊
We also adopted a monorepo setup in which the framework is made up of internal packages, each with their own individual APIs, type definitions, and tests. We wanted to make the dependencies between these modules more explicit, making it easier for developers to read, understand, and make changes to all. This was key to our endeavor to lower the project’s contribution barriers and improve its long-term maintainability.
我們采用了 monorepo 來構(gòu)建內(nèi)部模塊防楷,每個模塊都有單獨(dú)的 API 牺丙、類型定義和單元測試。這么做的目的是為了讓每個模塊之間的依賴更加清晰复局,讓開發(fā)者們閱讀代碼冲簿、理解邏輯和修改更加容易。這是我們努力降低項(xiàng)目貢獻(xiàn)門檻亿昏、提高長期可維護(hù)性的關(guān)鍵峦剔。
發(fā)起 RFC 流程
By the end of 2018, we had a working prototype with the new reactivity system and virtual DOM renderer. We had validated the internal architectural improvements we wanted to make, but only had rough drafts of the public-facing API changes. It was time to turn them into concrete designs.
We knew we had to do this early and carefully. Vue’s widespread usage means breaking changes can lead to massive migration costs for users and potential ecosystem fragmentation. To ensure users would be able to provide feedback on breaking changes, we adopted an RFC (Request for Comments) process at the beginning of 2019. Each RFC follows a template, with sections focused on motivation, design details, trade-offs, and adoption strategies. Since the process is conducted in a GitHub repo with proposals submitted as pull requests, discussions unfold organically in the comments.
The RFC process has proven immensely helpful, serving as a thought framework that forces us to fully consider all aspects of a potential change, and allowing our community to participate in the design process and submit well-thought-out feature requests.
在 2018 年底,我們有了新的響應(yīng)式系統(tǒng)和虛擬 DOM 渲染器的原型角钩。盡管已經(jīng)驗(yàn)證了內(nèi)核結(jié)構(gòu)性升級的構(gòu)想羊异,但是的對公眾開放的 API 改動信息只有一些簡陋的草案。這正是將草案正式落地的時候彤断。我們也清楚,做 RFC 必須非常謹(jǐn)慎易迹, 如今 Vue 的流行度意味著破壞性改動會導(dǎo)致用戶或者潛在的生態(tài)圈花費(fèi)大量的成本遷移宰衙。為了確保用戶能對破壞性改動提出反饋,我們在 2019 年初啟用了 RFC (Request for Comments) process 睹欲。每一條 RFC 都遵循固定模板:修改動機(jī)供炼、設(shè)計細(xì)節(jié)、權(quán)衡考慮及采取的策略窘疮。由于 RFC 在 Github 倉庫中新型袋哼,提案以 PR (Pull Request) 的形式提出,使得對于 RFC 討論也能在評論區(qū)中展開來闸衫。事實(shí)證明:開展 RFC 非常有效涛贯。它促使我們對于隱式的改動進(jìn)行更周全的考慮,也允許社區(qū)參與到設(shè)計流程并提交更成熟的方案中蔚出。
更快更小
Performance is essential to frontend frameworks. Although Vue 2 boasts competitive performance, the rewrite offers an opportunity to go even further by experimenting with new rendering strategies.
對于一個框架來說弟翘,性能是非常重要的虫腋。盡管 Vue 2 的性能非常優(yōu)異,但新的渲染策略中對于性能能更上一層樓稀余。
克服虛擬 DOM 的瓶頸
Vue has a fairly unique rendering strategy: It provides an HTML-like template syntax but compiles the templates into render functions that return virtual DOM trees. The framework figures out which parts of the actual DOM to update by recursively walking two virtual DOM trees and comparing every property on every node. This somewhat brute-force algorithm is generally pretty quick, thanks to the advanced optimizations performed by modern JavaScript engines, but updates still involve a lot of unnecessary CPU work. The inefficiency is particularly obvious when you look at a template with largely static content and only a few dynamic bindings—the whole virtual DOM tree still needs to be recursively walked to figure out what’s changed.
Vue 具有相當(dāng)獨(dú)特的渲染策略:提供了類 HTML 的模板語法悦冀,可以編譯成一個返回虛擬 DOM 樹的渲染函數(shù) (譯者注:模板字符串編譯成 JS 函數(shù)表達(dá)式)。Vue 框架能通過遞歸比對兩顆虛擬 DOM 樹的差異睛琳,計算出哪一部分的真實(shí) DOM 需要更新盒蟆。由于現(xiàn)代 JavaScript 引擎比較給力,這種略暴力的算法總體來說并不慢师骗,但是也造成了不少不必要的 CPU 計算历等,尤其是對于一個由絕大部分靜態(tài)內(nèi)容和極少數(shù)動態(tài)綁定的大型模板來說由非常明顯的性能短板。因?yàn)檎麄€ DOM 樹仍然需要遞歸地算出哪一部分需要更新丧凤。
Luckily, the template compilation step gives us a chance to perform a static analysis of the template and extract information about dynamic parts. Vue 2 did this to some extent by skipping static sub-trees, but more advanced optimizations were difficult to implement due to the overly simplistic compiler architecture. In Vue 3, we rewrote the compiler with a proper AST transform pipeline, which allows us to compose compile-time optimizations in the form of transform plug-ins.
幸運(yùn)的是募闲,我們能在模板編譯這一階段進(jìn)行靜態(tài)分析,并抽離動態(tài)的部分愿待。雖然 Vue 2 做了一些跳過一些靜態(tài)子節(jié)點(diǎn)的優(yōu)化操作浩螺,但是這過于簡單粗暴,對于一些更進(jìn)一步的優(yōu)化難以實(shí)現(xiàn)仍侥。在 Vue 3.0 中要出,我們重寫了一種能結(jié)合編譯期優(yōu)化的 AST (Abstract Syntax Tree 抽象語法樹)轉(zhuǎn)換管道插件。
With the new architecture in place, we wanted to find a rendering strategy that would eliminate as much overhead as possible. One option was to ditch virtual DOM and directly generate imperative DOM operations, but that would eliminate the ability to directly author virtual DOM render functions, which we’ve found to be highly valuable to advanced users and library authors. Plus, it would be a huge breaking change.
有了新的架構(gòu)农渊,我們希望找到一種盡可能減少開銷的渲染策略患蹂。一種選擇是放棄虛擬
DOM,直接生成命令式 DOM 操作砸紊,但這將消除直接編寫虛擬 DOM 呈現(xiàn)函數(shù)的能力传于,我們發(fā)現(xiàn)這對高級用戶和庫作者非常有價值。另外醉顽,這將是一個巨大的突破性變化沼溜。
The next best thing was to get rid of unnecessary virtual DOM tree traversals and property comparisons, which tend to have the most performance overhead during updates. In order to achieve this, the compiler and the runtime need to work together: The compiler analyzes the template and generates code with optimization hints, while the runtime picks up the hints and takes fast paths whenever possible. There are three major optimizations at work here:
另一種極好的方法是消除不必要的虛擬 DOM 樹遍歷和屬性比較,它們在更新過程中往往性能開銷最大游添。為了實(shí)現(xiàn)這一點(diǎn)系草,編譯器和運(yùn)行時需要協(xié)同工作:編譯器分析模板并生成帶有優(yōu)化提示的代碼,而運(yùn)行時則獲取這些提示唆涝,并盡可能采用快速路徑找都。這里有三個主要的優(yōu)化:
First, at the tree level, we noticed that node structures stay completely static in the absence of template directives that dynamically alter the node structure (e.g., v-if and v-for). If we divide a template into nested “blocks” separated by these structural directives, the node structures within each block become completely static again. When we update the nodes within a block, we no longer need to recursively traverse the tree—dynamic bindings within the block can be tracked in a flat array. This optimization circumvents much of the virtual DOM’s overhead by reducing the amount of tree traversal we need to perform by an order of magnitude.
首先,在虛擬 DOM 樹層面廊酣,我們注意到節(jié)點(diǎn)結(jié)構(gòu)在沒有動態(tài)改變節(jié)點(diǎn)結(jié)構(gòu)的模板指令(例如 v-if 能耻、 v-for)的情況下保持完全靜態(tài)。如果我們將一個模板劃分成由這些結(jié)構(gòu)指令分隔開的嵌套“塊”,那么每個塊中的節(jié)點(diǎn)結(jié)構(gòu)將再次變得完全靜態(tài)嚎京。當(dāng)我們更新塊中的節(jié)點(diǎn)時嗡贺,我們不再需要遞歸地遍歷樹,塊中的動態(tài)綁定可以在平面數(shù)組中跟蹤鞍帝。這種優(yōu)化通過將需要執(zhí)行的樹遍歷量減少一個數(shù)量級诫睬,從而避免了虛擬 DOM 的大部分開銷。
Second, the compiler aggressively detects static nodes, subtrees, and even data objects in a template and hoists them outside the render function in the generated code. This avoids recreating these objects on each render, greatly improving memory usage and reducing the frequency of garbage collection.
第二帕涌,編譯器積極地檢測模板中的靜態(tài)節(jié)點(diǎn)摄凡、子樹甚至數(shù)據(jù)對象,并將它們提升到生成代碼的渲染函數(shù)之外蚓曼。這樣可以避免在每個渲染器上重新創(chuàng)建這些對象亲澡,從而大大提高內(nèi)存使用率并降低垃圾回收的頻率。
Third, at the element level, the compiler also generates an optimization flag for each element with dynamic bindings based on the type of updates it needs to perform. For example, an element with a dynamic class binding and a number of static attributes will receive a flag that indicates only a class check is needed. The runtime will pick up these hints and take the dedicated fast paths.
第三纫版,在元素層面床绪,編譯器還會根據(jù)需要執(zhí)行的更新類型,為每個元素生打上優(yōu)化標(biāo)記其弊,并使用動態(tài)綁定癞己。例如,具有動態(tài)類綁定和許多靜態(tài)屬性的元素將收到一個標(biāo)志梭伐,該標(biāo)志指示只需要進(jìn)行類檢查痹雅。運(yùn)行時將獲取這些提示并使用專用的快速路徑。
Combined, these techniques have significantly improved our render update benchmarks, with Vue 3 sometimes taking less than a tenth of Vue 2’s CPU time. (CPU time That is, time spent performing JavaScript computations, excluding browser DOM operations.)
這些技術(shù)結(jié)合起來糊识,極大地提高我們的渲染更新 benchmarks绩社,某些時候 Vue 3 占用的 CPU 時間還不到 Vue 2 的十分之一。(CPU時間赂苗,即 JavaScript 執(zhí)行的時間愉耙,不包括瀏覽器 DOM 操作)
最小化構(gòu)建體積
The size of the framework also affects its performance. This is a unique concern for web applications because assets need to be downloaded on the fly, and the app will not be interactive until the browser has parsed the necessary JavaScript. This is particularly true for single-page applications. While Vue has always been relatively lightweight—Vue 2’s runtime size is around 23 KB gzipped—we’ve noticed two problems:
對于 Web 應(yīng)用程序來說,有一個獨(dú)特的問題:框架的體積也會影響性能拌滋,因?yàn)槟_本資源需要動態(tài)下載劲阎,并且在瀏覽器解析 JavaScript 之前,應(yīng)用程序是不能交互的鸠真。對于 SPA 尤其如此。盡管 Vue 一直是相對輕量級的龄毡,Vue 2 的運(yùn)行時(排除模板編譯相關(guān)的代碼)代碼體積約為23 KB吠卷,我們注意到兩個問題:
First, not everyone uses all of the framework’s features. For example, an app that never uses the transition features still pays the download and parse costs of transition-related code.
首先,不是所有的開發(fā)者都會使用框架里面的全部功能沦零。比如:有些應(yīng)用壓根就不用動畫相關(guān)的功能祭隔,但這部分功能也要跟著框架一起下載和解析。
Second, the framework keeps growing indefinitely as we add new features. This gives bundle size disproportionate weight when we consider the trade-offs of a new feature addition. As a result, we tend to only include features that will be used by the majority of our users.
其次,框架是不定期更新增加新功能的疾渴,代碼體積的增大千贯,同新功能添加是不成比例的(添加一個新功能指不定要多寫多少代碼)。結(jié)果就是我們?yōu)榻^大部分用戶只提供最基本功能的代碼搞坝。
Ideally, the user should be able to drop code for unused framework features at build time—also known as “tree-shaking”—and only pay for what they use. This would also allow us to ship features that a subset of our users would find useful without adding payload costs for the rest.
理想情況下搔谴,用戶應(yīng)該能夠在構(gòu)建時消除代碼引入模塊中沒有用到的部分,也就是所謂的 tree-shaking (可以理解為按需加載)桩撮。如果不增加其他功能的話敦第,就不需要下載額外的代碼。
In Vue 3, we achieved this by moving most of the global APIs and internal helpers to ES module exports. This allows modern bundlers to statically analyze the module dependencies and drop code related to unused exports. The template compiler also generates tree-shaking friendly code, which only imports helpers for a feature if the feature is actually used in the template.
在 Vue 3 中店量,我們通過將大部分全局 API 和內(nèi)部輔助函數(shù)移到 ES module (ES module 是JavaScript 模塊實(shí)現(xiàn)的一種方案芜果,也是目前主流的一種)的 export 來實(shí)現(xiàn)這一點(diǎn)。這使得現(xiàn)代的 bundler 能夠靜態(tài)地分析模塊依賴關(guān)系融师,并刪除與未使用的導(dǎo)出相關(guān)的代碼右钾。模板編譯器還生成 tree-shakng 友好代碼,只有在模板中實(shí)際使用了某個功能時旱爆,才會為該功能導(dǎo)入輔助函數(shù)舀射。
Some parts of the framework can never be tree-shaken because they’re essential to any type of app. We call the measure of these indispensable parts the baseline size. Vue 3’s baseline size is around 10 KB gzipped—less than half that of Vue 2, despite the addition of numerous new features.
框架的核心部分永遠(yuǎn)不會被 tree-shakng,因?yàn)樗鼈儗θ魏晤愋偷膽?yīng)用程序都是必不可少的疼鸟。我們稱這些不可缺少的部分的度量稱為基礎(chǔ)尺寸后控。盡管增加了許多新特性,Vue 3 通過 gzip 壓縮后空镜,基礎(chǔ)尺寸只有 10 kb浩淘,比 Vue2 的一半還小(譯者注:盡管這個壓縮非常極致吴攒,但是受益場景越來越小张抄,因?yàn)楝F(xiàn)在的網(wǎng)速越來越不值錢,這一優(yōu)化今后可能只會在弱網(wǎng)情況下得以體現(xiàn))洼怔。
滿足大規(guī)模項(xiàng)目需求
We also wanted to improve Vue’s ability to handle large-scale applications. Our initial Vue design focused on a low barrier to entry and a gentle learning curve. But as Vue became more widely adopted, we learned more about the needs of projects that contain hundreds of modules and are maintained by dozens of developers over time. For these types of projects, a type system like TypeScript and the ability to cleanly organize reusable code are critical, and Vue 2’s support in these areas was less than ideal.
我們也希望提升 Vue 對于大型應(yīng)用開發(fā)的能力署惯。一開始 Vue 的設(shè)計初衷著眼于降低開發(fā)門檻和學(xué)習(xí)曲線。然而隨著 Vue 的使用越來越廣泛镣隶,我們理解了許多由幾十個開發(fā)者維護(hù)上百個模塊的痛點(diǎn)极谊。使用類似于 TypeScript 的類型檢查系統(tǒng)是能清晰組織可復(fù)用代碼的關(guān)鍵,可惜 Vue 2 在這方面的支持沒有想象中那么高安岂。
In the early stages of designing Vue 3, we attempted to improve TypeScript integration by offering built-in support for authoring components using classes. The challenge was that many of the language features we needed to make classes usable, such as class fields and decorators, were still proposals—and subject to change before officially becoming part of JavaScript. The complexity and uncertainty involved made us question whether the addition of the Class API was really justified, since it didn’t offer anything other than slightly better TypeScript integration.
在設(shè)計 Vue 3 的早期階段轻猖,我們試圖通過提供對使用類編寫組件的內(nèi)置支持來改進(jìn)TypeScript集成。在成為 JavaScript 的一部分之前域那,我們?nèi)匀恍枰薷?JavaScript 類的許多特性咙边。所涉及的復(fù)雜性和不確定性使我們懷疑添加類 API 是否真的合理,因?yàn)槌松晕⒑靡稽c(diǎn)的 TypeScript 集成之外,它沒有提供任何東西败许。
We decided to investigate other ways to attack the scaling problem. Inspired by React Hooks, we thought about exposing the lower-level reactivity and component lifecycle APIs to enable a more free-form way of authoring component logic, called Composition API. Instead of defining a component by specifying a long list of options, the Composition API allows the user to freely express, compose, and reuse stateful component logic just like writing a function, all while providing excellent TypeScript support.
我們決定研究其他方法來解決縮放問題王带。受React Hooks的啟發(fā),我們考慮暴露底層的響應(yīng)式和組件生命周期API市殷,以支持一種更靈活的方式編寫組件邏輯愕撰,稱為Composition API (不翻譯,可以理解為組合 API)被丧。 Composition API 不是通過定義一大坨 option 屬性代碼來編寫組件盟戏,而是允許用戶像編寫函數(shù)一樣自由地表達(dá)、組合和重用有狀態(tài)的組件邏輯甥桂,所有這些都提供了出色的 TypeScript 支持柿究。
We were really excited about this idea. Although the Composition API was designed to address a specific category of problems, it’s technically possible to use it only when authoring components. In the first draft of the proposal, we got a bit ahead of ourselves and hinted that we might replace the existing Options API with the Composition API in a future release. This resulted in massive pushback from community members, which taught us a valuable lesson about communicating longer-term plans and intentions clearly, as well as understanding users’ needs. After listening to feedback from our community, we completely reworked the proposal, making it clear that the Composition API would be additive and complementary to the Options API. The reception of the revised proposal was much more positive, and received many constructive suggestions.
我們對這個想法非常興奮。盡管 Composition API 是為解決特定類別的問題而設(shè)計的黄选,但技術(shù)上講蝇摸,只有在編寫組件時才使用它是可能的。在提案的初稿中办陷,我們有點(diǎn)超前貌夕,并暗示在將來的版本中,我們可能會用 Composition API 替換現(xiàn)有的 Options API (也就是 Vue 2 中的 data 民镜、props啡专、methods 等)。這導(dǎo)致了社區(qū)成員的強(qiáng)烈反對制圈,這給我們上了一堂寶貴的一課:清楚地傳達(dá)長期計劃和意圖们童,以及理解用戶的需求。在聽取了社區(qū)的反饋意見后鲸鹦,我們對提案進(jìn)行了全面的修改慧库,明確了 Composition API 將是 Options API 的補(bǔ)充和補(bǔ)充,對修改后的提案的接受度更高馋嗜,并收到了許多建設(shè)性的建議齐板。
尋求平衡點(diǎn)
Among Vue’s user base of over a million developers are beginners with only a basic knowledge of HTML/CSS, professionals moving on from jQuery, veterans migrating from another framework, backend engineers looking for a frontend solution, and software architects dealing with software at scale. The diversity of developer profiles corresponds to the diversity of use cases: Some developers might want to sprinkle interactivity on legacy applications, while others may be working on one-off projects with a fast turnaround but limited maintenance concerns; architects may have to deal with large-scale, multiyear projects and a fluctuating team of developers over the project’s lifetime. Vue’s design has been continuously shaped and informed by these needs as we seek to strike a balance between various trade-offs. Vue’s slogan, “the progressive framework,” encapsulates the layered API design that results from this process. Beginners can enjoy a smooth learning curve with a CDN script, HTML-based templates, and the intuitive Options API, while experts can handle ambitious use cases with full-featured CLI, render functions, and the Composition API.
Vue 擁有超過100萬的開發(fā)者,其中包括只掌握 HTML/CSS 基本知識的初學(xué)者葛菇、從jQuery 轉(zhuǎn)行的專業(yè)人士甘磨、從其他框架遷移過來的老司機(jī)、尋找前端解決方案的后端工程師以及大規(guī)模處理軟件的軟件架構(gòu)師眯停。開發(fā)者們各種各樣的配置對應(yīng)著各種各樣的使用場景:一些開發(fā)人員可能希望在某些老項(xiàng)目上增加交互性济舆,而另一些開發(fā)人員則可能致力于一次性項(xiàng)目,其開發(fā)周期很短而維護(hù)有限庵朝;架構(gòu)師可能必須處理大型、祖?zhèn)鞔a和不斷變化的團(tuán)隊(duì)項(xiàng)目生命周期內(nèi)的開發(fā)者(鐵打的代碼,流水的程序員←.←)九府。
Vue 的設(shè)計一直在不斷地被這些需求所塑造椎瘟,在各種權(quán)衡之間尋求平衡。Vue 的口號“漸進(jìn)式框架”封裝了從這個過程中產(chǎn)生的分層API設(shè)計侄旬。初學(xué)者可以通過 CDN 腳本肺蔚、基于 HTML 的模板和直觀的 Options API 享受流暢的學(xué)習(xí)曲線拇囊,而老司機(jī)們可以通過全功能的 CLI 工具戴而、渲染函數(shù)和 Composition API 來駕馭一些復(fù)雜場景喇颁。
There’s still a lot of work left to do to realize our vision—most importantly, updating supporting libraries, documentation, and tools to ensure a smooth migration. We’ll be working hard in the coming months, and we can’t wait to see what the community will create with Vue 3.
要實(shí)現(xiàn)我們的愿景還有很多要做的事坚弱,最重要的還是更新支持庫泵肄、文檔和工具灼狰,以確保順利遷移进萄。我們將在接下來的幾個月里繼續(xù)致力于上面的工作已烤。這個社區(qū)將用 Vue 3 創(chuàng)造出什么族操,讓我們拭目以待苛坚!