Vue2 徹底從 Flow 重構爲 TypeScript,煥然一新!

事情起源於 4 月 7 號晚上,尤雨溪在推特說,Vue2 收到了一個將整個代碼庫遷移到 TypeScript 的 PR。

Evan's twitter

去 Github 圍觀了一下 chore: move to typescript 這個 PR[1],基本上是 10w 行級別代碼量的改動,把整個 Vue2 的代碼庫從原先的 flow 類型系統全部遷移到了 TypeScript,包括代碼、構建系統、各種 lint 工具等等,恐怖的戰鬥力!

Github PR

這個 PR 的貢獻者是 Carlos Rodrigues[2],以下是他的自我介紹:

Fullstack developer, interested in @vuejs, @dotnet and @nodejs.

Typescript 🧙‍♂️

Consultant 🕵️‍♂️

全棧開發工程師,Vue.js、dotnet、Node.js 的愛好者。

TypeScript 魔法師 🧙‍♂️

顧問 🕵️‍♂️。

起源

Vue2 爲什麼最開始選擇 Flow 作爲類型系統?其實在一個 2016 年的知乎問題 Vue 2.0 爲什麼選用 Flow 進行靜態代碼檢查而不是直接使用 TypeScript?[3] 裏,尤雨溪已經詳細說明了這個問題,以下是當時他的回答:

這個選擇最根本的還是在於工程上成本和收益的考量

Vue 2.0 本身在初期的快速迭代階段是用 ES2015 寫的,整個構建工具鏈也沿用了 Vue 1.x 的基於 ES 生態的一套(Babel, ESLint, Webpack, Rollup...),全部換 TS 成本過高,短期內並不現實。

相比之下 Flow 對於已有的 ES2015 代碼的遷入 / 遷出成本都非常低:

  1. 可以一個文件一個文件地遷移,不需要一竿子全弄了。

  2. Babel 和 ESLint 都有對應的 Flow 插件以支持語法,可以完全沿用現有的構建配置;

  3. 更貼近 ES 規範。除了 Flow 的類型聲明之外,其他都是標準的 ES。萬一哪天不想用 Flow 了,用 babel-plugin-transform-flow-strip-types 轉一下,就得到符合規範的 ES。

  4. 在需要的地方保留 ES 的靈活性,並且對於生成的代碼尺寸有更好的控制力 (rollup / 自定義 babel 插件)

不過在 2018 年的時候,尤大更新了回答,真香定律再現:

真香

也正因如此,Vue3 從一開始就選擇了 TypeScript 作爲類型系統。

困擾

那麼也許有人要問,Vue2 不是已經穩定了嗎,何必再大費周章的把這麼多代碼遷移到 TypeScript 中呢?其實在之前 Vue3 放棄 IE11 的 RFC 中就有提及,之後還是會爲 Vue 2.7 去加入一些和 Vue3 語法更類似的功能:

而這些功能的開發和適配,如果繼續用 flow 的話,勢必會帶來一些割裂的開發體驗。一些已經用 TS 開發好的庫,也沒辦法做代碼的合併。事實上 Twitter 也有網友提出了這個問題,PR 作者進行了回答:

Why

簡單來說,就是爲 Vue 2.7 的開發做準備,尤其是 composition-api 的代碼合併。

具體內容

先看作者對這次更新的簡單描述:

  1. 代碼格式化風格更新。

  2. 重構。

  3. 構建相關的改動。

  4. 代碼庫更新爲 TypeScript 編寫。

值得一提的是,更換成 TS 之後,生成的代碼體積都有少量的增加,作者猜測是 TS 加入了一些 runtime 的代碼導致的:

第一個 Commit 中,作者把代碼的類型全部改成 .ts,移除文件開頭 flow 的標記,並且把類型的語法全部替換成 TypeScript:

作者用 TS 的 import type 語法重構了類型導入,我個人也比較喜歡這樣導入類型,更有助於區分導入的內容:

單測工具的更新,以及 TS 的支持,利用 ts-loader 做編譯:

RollUp 版本的一次大升級:

ESLint 也需要一些改動,使用 @typescript-eslint/parser,繼承的一些推薦預設也改爲 @typescript-eslint/eslint-recommended

CI 中原本 flow 的類型檢測,也改成使用 tsc --noEmit 做 TS 的類型檢查。

評價

可怕的是,這個如此龐大的 PR 是作者在幾天內完成的,這戰鬥力簡直是驚人。

Twitter 的評論中有人提問:“把如此巨大的代碼庫遷移到 TypeScript 需要多長時間?”

作者回答:在幾小時內重命名文件,把 flow types 重寫成 TS 類型並修復錯誤,之後的幾天主要是忙構建、測試相關的工作。

對此,外國推友也表示很震驚:

“你簡直是個機器”:

“他生活的宇宙中,1 小時可以頂我們 24 小時,或者也可能他是用光速在敲代碼”

CamiloR:“太棒了,很高興核心團隊之外,也有人付出如此多的努力”

Carlos:“我就是核心團隊的成員 😆”

總結

不得不感嘆,十倍工程師是真實存在的…… 這樣一次巨型代碼庫遷移只花了短短几天時間,其實也體現出作者在 TS 生態、構建以及測試相關方面的熟悉程度。

感謝 Vue 核心團隊成員們誇張的戰鬥力,給前端界帶來這麼優秀的框架而且持續迭代和優化。

Vue 3 雖然是未來,但是 Vue 2 也不會被放棄,遷移到 TS 以後的 Vue 2 具有更強的代碼可移植性,一定會綻放出更多精彩。

參考資料

[1]

chore: move to typescript 這個 PR: https://github.com/vuejs/vue/pull/12001/commits

[2]

Carlos Rodrigues: https://twitter.com/pikax_dev

[3]

Vue 2.0 爲什麼選用 Flow 進行靜態代碼檢查而不是直接使用 TypeScript?: https://www.zhihu.com/question/46397274/answer/101193678

[4]

@vue/composition-api plugin: https://github.com/vuejs/composition-api

[5]

script setup: https://github.com/vuejs/rfcs/pull/227

[6]

非官方插件: https://github.com/underfin/vite-plugin-vue2

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/QPZusSE-70lBEJ_K5bv8KA