Vue 2.0 為什麼選用 Flow 進行靜態代碼檢查而不是直接使用 TypeScript?

掃了最新的2.0源碼,和幾周前已經面目全非,細看了一下應該是使用了Flow的原因,隨手看了一下React 項目也是依賴了 Flow 的,Flow是由Facebook 團隊的項目開發的,那麼 React 支持一下自家的項目也很正常。Vue 選用Flow而非TypeScript 的原因是什麼? 哪些方面Flow更優秀(話說工具只支持Linux和Mac這個真的很奇怪呀)

另外一方面是否說明了隨著前端工程實踐的發展,這類靜態檢查的工具已經開始扮演越來越重要的角色了?(你看,幾個主流的前端框架都開始使用了嘛):

React Flow

Vue Flow

Angular 2.0 TypeScript


這個選擇最根本的還是在於工程上成本和收益的考量。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 插件)

第三點額外說一些:這一點上 Facebook 應該也是同樣的考量,寧可貼近規範而不是用一個被 M$ 控制的、一旦使用難以遷出的語言。為什麼 Angular 就願意用 TS 呢?因為 Angular 本來就是一幫搞 Java 的人弄出來的,而且只是 Google 的一個子項目,Google 在公司層面根本不關心它用什麼語言。而對 Facebook 來說 React/ReactNative/Babel/Flow/Nuclide 是整個公司 infrastructure 層面的東西,要麼依賴規範,要麼就得自己有控制權。

編輯器 / IDE 方面,Atom + Nuclide 其實也還湊合,type warning / type hint / autocomplete / jump to definition 都有,就是 Atom 本身慢了點。

至於重構、設計什麼的,我只想說,看的是使用的人的水平,跟用什麼語言沒那麼大關係。水平爛的人用 TS 一樣寫的是翔一樣的代碼,看看 java 就知道了。

另外注意我並沒有說 TS 不好,但是在 Vue 的需求和現狀下 Flow 是更合理的選擇。


說點作為 ng 黨政治不正確的內容。。

所謂 Angular 2 採用 TypeScript 並不準確,雖然 Angular 2 使用 TypeScript 開發,但是 Angular 2 的項目是可以自由地使用 TypeScript、ES next、ES5 的。。當然前面那句廢話不重要,重要的是目前 Angular 2 基於 ES next 的項目也是大量使用 Flow.js 來實現基於類型標註的依賴注入的。。

ng 官方的文檔只給了 TypeScript 和 ES5 的版本,完全沒有照顧大量的中間選民,中間選民肯定還是存在的,甚至可能是沉默的大多數(大誤)。。

從 AngularClass (GitHub - AngularClass/awesome-angular2: A curated list of awesome Angular 2 resources by @AngularClass)給出的 Babel 模板項目中:

Babel Seed Projects

  • babel-angular2-app A skeleton Angular 2 app built with Babel and Browserify.
  • angular2-fullstack-starter A full stack skeleton Angular 2 app built with Webpack/Babel.
  • angular2-es6-starter A skeleton Angular 2 ES6 application built with Babel, Webpack, Gulp.
  • angular2-es-seed A complete, yet simple, starter for Angular 2 using ES2016.
  • {{ add_your_repo }}

上面全部的 4 個項目都使用的 babel-preset-angular2 或直接使用 babel-plugin-angular2-annotations(前者是對後者以及 babel-plugin-transform-flow-strip-types 等 plugins 的封裝),用法可以參照 Angular 2 with Babel 所述。

當然,事實上,這是僅僅是借用了 Flow.js 的類型標註語法,然後利用另外的插件把基於 Flow.js 語法的類型標註轉換成 ng2 的依賴注入,然後清除 Flow.js 的類型標註,並沒有真正使用 Flow.js 的類型檢查。。不過既然都用了 Flow.js 的類型標註了,順便用下 Flow.js 來做做類型檢查其實也是不錯的選擇。。

所以,雖然使用框架需要按照官方的基本法,但是社區的決定權也很重要,不要聽風就是雨。官方所謂的最佳實踐是一種指導、而非一種限制,未必適合每一個人,自己的項目選擇合適自己的工具鏈就好。(當然生態也很重要)

綜上,在 ng2 中當然也可以使用 Flow.js,同理,在 React 和 Vue 中一樣也可以使用 TypeScript。。至於為什麼官方不同時提供兩種工具的支持,那是其他人的喜好或者利益問題。。

最後為並沒有真正回答本問題表示歉意。。O=&>_&<=O(這是一個 Lambda 表達式)


有個區別,Flow 只做類型檢查,你只需要在你需要的地方加上聲明就可以。而 Typescript 和 babel 有功能上的重疊,可能對你的代碼有侵入,要用就要用全套,但 Typescript 有 vs code 這個紅利,如果完全用 ts 開發可以擁有近似靜態語言的開發體驗。


Vue 採用 Flow 明智之舉,因為真的用Typescript來寫Vue,你會發現你根本寫不下去!

Flow 相比 Ts 來說,加入類型要比Ts,少配置tsconfig、tslint,使用的靜態類型更少。所以對於Vue的受眾群體來說,非常實用。

而Ts完全可以在你需要的地方配置靜態類型,你也可以通過AllowJS來Import 你的JS 包。

那麼為什麼Vue用Typescript寫不下去呢?我們所知道Vue的黑魔法實在是太多了,滿足了快速開發的需求,學習起來也容易上手。可真因為是這個原因,所以,用TS寫,成本實在是高到離譜。

眾所周知,Vue.Component(更確切的應該是Vue.extends)幾乎算是配置型的構建模型,你可能會用到props、filter、watch、computed,methods以及最常用的data等等。

Vue最值得讓人稱讚的地方就是:當我想要訪問props / $data / methods / computed等它們的對象,可以通過 this.[它們的屬性] 就可以輕鬆的得到你想要的,你說爽不爽,實在是爽到6666

可是 Typescript 這傢伙,不接受呀,我只知道你是props / $data / computed里變數的類型,可是TS很笨,讀不到呀。這時候,你得很誠懇的給this這些已有的屬性綁上類型。

比如這樣:

interface IProps {

myProps1: number,

myProps2: string

....

}

interface IData {

myProps1: number,

myProps2: string

....

}

interface ... { ... }

class vueComponent extends Vue&< IProps, IData, ...&>

當然還得寫個#VueComponent,主動把IProps綁到 props里, IData綁到$data/data 里... 真是羅嗦..

或者這樣

// # 代表 @

class VueComponent {

propsType

dataType..

#Watch("onWatchedTwoChange", {deep: true})

watchedTwo:string = "watch two";

#props simple_prop:string = "default val";

#computed

.....

}

再看看我們常寫的directive,還得寫一個#params吧。

Vue.directive("example", {
params: ["a"],
bind: function () {
console.log(this.params.a) // -&> "hi"
}

})

再看看讓我們愛不釋手的Template:裡邊的變數真的不需要加類型嗎?

什麼?IDE沒有模板變數和語法提示?靜態類型不能夠被IDE識別?只能在編譯時?看來還是只能做煩燥地CTRL+C了。

這時你的工作量就是正常寫Typescript的2倍以上,當然你也可以只是寫寫props靜態類型就好了,不過上Flow 就好了,為什麼要上Typescript這麼龐大的系統。

對於Vue的使用者都這麼難受了,何況是用TS來開發Vue?

watch 依賴 v-model, computed可能依賴watch或者v-model,也可能相互交叉引用,想寫類型?先把它們之間的依賴關係弄明白,再寫吧。

所以不得不說 Flow 真的是明智之舉,盛讚。


一下子轉TS,有些人會突然寫不出代碼;

TS確實是重構利器,起碼私有、共有、抽象什麼的都很清晰了,如果用繼承模式擴展開發則是另外的體驗,比較接近傳統的GUI類庫,設計者沒有一定功力駕馭不住,容易被吐槽;

用TS跟沒用的區別應該是,很快會出3吧;

利益相關:ts nc粉


java/.net 程序員的思維模式基於class和interface 使用typescript沒有切換成本

js程序員習慣的思維模式是object delegation 寫代碼的時候連new都不用 基本上只使用Object.create 自誇一句 js才是真正的object oriented language 丫就沒有class ES6的class也只是語法糖

這兩種思維模式寫出來的代碼是不一樣的 現在沒看出來切換到ts 能讓vue變得更好 反倒有可能讓開發更麻煩 用flow簡單多了


推薦閱讀:

如果ECMAScript 2015+完全普及,原型鏈這種知識是否還有了解的必要?
webpack 只適合SPA嗎?
能否用通俗語言講一下web前端講的「切圖」到底是什麼意思?
js等語言的undefined值存在的意義是什麼?
npm install的實現原理?

TAG:前端開發 | Vuejs |