Web Component 和類 React、Angular、Vue 組件化技術誰會成為未來?

類比現在 HTML5 和 RN、Weex 技術體系,標準的 HTML5 顯然是無線端的未來(只不過時間未知),特別是 PWA 技術等技術的興起,會進一步推進,起碼有點希望。

反觀 Web Component 是 W3C 專門為組件化創建的標準,包括一些 Shadow DOM 等特性徹底的、從瀏覽器的層面解決掉一些作用域的問題(例如全局覆蓋的 CSS)。而且也不需要構建、編譯,直接跑在瀏覽器上。但是因為眾多坑導致一直難以流行。有一些大公司(例如 Google)也研發一些框架來推進,但是也像 HTML5 在 Facebook 那樣受到了挫折。

與此同時 React、Angular、Vue 等組件化技術體系異軍突起,自建的 DSL 也帶出了前端編譯、構建器整個生態,出現了各種庫、生態、概念。但是解決類似 CSS 作用域的問題,還是基於現有技術想辦法繞過(CSS in JS)。但是入門、開發成本也相對提高,開發一個新項目,配置一整套構建配置等也比較麻煩。

那麼問題來了,你認為 React、Angular、Vue 等 DSL 會採納入 W3C 標準成為推薦標準?比如瀏覽器直接支持 JSX 等,不再需要編譯就可以運行,並且支持作用域等能力,廢掉 Web Component 標準。還是 Web Component 坑逐步填完,逐步被瀏覽器支持最終成為未來?

===

關於現有 JSX 直接被瀏覽器支持是不可能的,因為不同的庫編譯出來的 API 不一樣。我想表達的意思是標準直接取了一套最流行穩定的組件化技術和概念,直接通過標準內置進去。比如吸取 React 的 生命周期的方式和創建 Component 的方式,結合 Web Component 產出新的規範。從簡單的角度來看,React 的 JSX 調用方法和 Web Component 組件拼裝方法,都是按照類似 HTML 的方式嵌套調用自定義的增強組件,這裡說的是把 JSX 的特性、語法引入進來。


一點補充內容:

Web 「相關」規範(這裡包括 Web API、ECMAScript 語言和常用的 Protocol 等)設計中一般有一些基本的共識:

  • 每一個 Web API 只做一件事;
  • 同一個功能不會有兩個類似的 API 來做(除非是用新的 API 來取代過於落後的 API);
  • 保持 ECMAScript 的平台無關性;
  • 保持 Web API(IDL 及語義)不強依賴於 ECMAScript;

比如我們能夠發現:

  • Web Components 不是一個規範,裡面的每個規範都是獨立的,並且其功能是有意義的。例如我們可以只用 Custom Elements 來擴展 HTML 語義;使用 Shadow DOM 來隔離 CSS;使用 Template Tag 來實現動態 DOM 生成;使用 HTML Imports 來引入外部內容等。
  • Web 的本質是一個平台,所有 API 都是平台的底層 API,首要目的也不是為了方便使用。除了類似於 XHR 或者 document.getElementByXXX 這樣過於繁瑣的 API 已經出現了替代品之外,並不會有出一個 Fetch 規範、一個 Request 規範、一個 SuperAgent 規範來滿足不同用戶的喜好。所有不影響功能實現的需求都應當自己通過封裝來解決。
  • ECMAScript 語言本身不會出現依賴於 DOM API 的內容。
  • 雖然 ECMAScript 目前是事實上被欽定的 Web 開發語言,但是所有 Web API 規範中都是用的語言無關的 Web IDL 來定義的,幾乎不會出現(顯式)依賴於 ECMAScript 的情況。

所以為了滿足題主實現類 React 框架的要求,可能的方式是:

  • ECMAScript 中增加 XML Literal 語法的支持,類似於 Scala 和 VB,增加一坨 Built-in 的類。
  • 復用現有的 Custom Elements API 作為組件基礎,其本身已經提供了良好的生命周期特性,沒有特殊的必要不可能重新引入一個類似的又沒什麼創新的同類 API。
  • DOM API 中增加一個 Virtual DOM API 子集,內置 Diff 功能,還要提供一套複雜的配置機制。

這樣做出來的效果也不會比目前好多少。

根本的問題在於,框架的職責在於提供一整套的解決方案,而平台 API 的設計要求是絕不能提供一整套的解決方案(即保證零耦合、正交),這是無法調和的基本矛盾所在。

---

先說觀點:Web Components 一定成不了氣候,但會繼續演進下去;Angular、React、Vue 誰也不會成為 Web 標準;JSX 永遠不可能得到原生支持。

現在 Web 前端的痛點並不在於「最新的」瀏覽器原生支持的特性不夠,而是「需要兼容」的瀏覽器原生支持什麼的問題。

Web 開發中,標準化的意義在於,

  1. 需求與實現的分離,例如某個類庫需要使用 Promise,但不需要糾結具體用哪個 Promise 實現,應用所有者自行 Polyfill 出來即可,避免出現用到了多個庫都分別自帶了自己私有的 Promise 實現;
  2. 知識和工具的復用性,例如大家都學的是同一個 JavaScript 語言/Web API,文檔和教程可以通用,避免每個人都去用自己的方言編譯到 JavaScript;
  3. 給 Web 開發指明一個&正確&合理的發展方向;
  4. 給 Web 平台提供更多的功能。

為什麼說 4 不是那麼重要呢?因為 Web 的使用方式確定了實現的滯後性,(相關)標準必然會領先於現有實現(如果要進步的話)。絕大多數人所做的都是通用 Web 開發,而非面向最新瀏覽器開發。被「規範」原生實現的東西,並不等於產品中可以視為原生實現,即便使用 Web Components,該構建還得構建(利於 extends HTMLElement 用到了 ES2015 的 class),該帶運行時還是得帶運行時(除了 & tag,Custom Elements、Shadow DOM 和 HTML Imports 顯然都需要對應 Polyfill)。

所以現實情況是,用「規範」定義的原生方案也需要 Compilation 和 Polyfill,用「第三方」的模擬方案也需要 Compilation 和 Polyfill,那麼這時候該如何選擇呢?為了 Web 規範的茁壯成長,大家為什麼不都主動選擇符合「規範」的方案呢?

不幸的是,「規範」永遠都是&落後&保守的。不論是功能覆蓋、API 設計還是可塑性。作為「規範」,這種取捨也是正確的。對於 Web 組件話方案而言,從 Angular、React 和 Vue 中任選一個,都能獲得比「規範」所提供的方案更多的功能、更快的反饋周期和更高的自主性。所以,在同樣需要 Compilation 和 Polyfill 的情況下,何樂而不為呢?

除了組件化之外,哪怕是 Fetch(Fetch API)這種可以算作及其先進的 Web API,也很容易看出這種弊端:雖然相比於 XHR 極大改善,但是本身功能仍然過於簡潔,在複雜應用中仍然需要自行封裝,隨著封裝力度的不斷加大,性價比還不如直接使用第三方的 HTTP 類庫。

所以回到框架的問題上,Angular、React 和 Vue 等 Web 框架(或者根據個人喜好叫類庫、平台)等,都不可能成為 Web 規範,或者說,不成為 Web 規範才是它們的意義所在。

如果對於一個 Web 框架,新增一個 Feature 需要過兩年才能使用,&提交一個 Bug 需要過兩年才能修復&(不不不,對於 Web 規範而言,沒有 Bug、只有 Feature,所謂的 BUG 只是特例而已,記住了就好,以後都會成為面試考點),這樣的 Web 框架還有何意義?

不過,雖然本身成為 Web 標準沒有意義,但是與 Web 標準共同發展仍然是一件好事。如果一個技術在 Web 框架中得到廣泛應用,那麼可能這個技術能夠成為 Web 標準的一部分;反之,如果一個 Web 標準得到廣泛支持,那麼 Web 框架也能在一定程度上受益於這些標準。

然後對於 JSX,目前所謂的 JSX 規範(facebook/jsx)只涉及語法,不涉及任何語義部分。也就是說,目前根本沒有規定對於一個 JSX 的擴展語法應該實現成什麼樣子。

React 會把它編譯成 React.createElement(),Vue 會編譯成 _h(),Inferno 會編譯成 createVNodes()。於是問題來了,用哪個 JSX 的實現作為標準呢?不光是命名空間,內部的結構組織大家也都不一樣。如果真要新增為 ECMAScript 的語言特性,那麼肯定是不會使用一個第三方的 namespace 的,於是作為標準化的語言特性,又增加了一種叫做「標準」實現的實現。但是另一方面,一旦要把 JSX 列入到 ECMAScript 中,也就意味著目前所有基於其他 JSX 實現的代碼全都會被 Break down。或者換句話說,就是因為大家本來都不打算讓 JSX 成為 ECMAScript 的一部分,才會分別大力發展自己的私有實現。

結合前面的部分,就算實現了,並不影響你所需的構建步驟(對於通用 Web 應用而言),然後又與所有當前的代碼不兼容,完全沒有必要這樣自找麻煩。

Web 開發永遠會趨向於「在保證可實現性的基礎上儘可能提高生產力」的開發方式,即便現在的 Web Components 真的被普遍實現了,大家也會繼續追求新的擴展以及新的高層抽象。

總結:

  • Web 開發由於其存在方式,必然需要在「避免構建」和「提高生產力」之前作出選擇;
  • Web 標準必將長期保持領先於「瀏覽器實現」,落後於「可行的最先進方案」的狀態;
  • Web 框架/類庫/平台的先進性可能需要其不被標準化才能持續保持;
  • JSX 沒有一個統一的語義,且平台相關性過於顯著,不太可能被吸收進 ECMAScript。


無論是過去現在還是未來,組件化開發的思想和實踐都會是行業現實,在沒有React,Angular,WebComponent之前,不少框架已經有很多嘗試了。現在進行的只不過是找到一種比較好的抽象而已。如果要成為標準,我認為Google的技術更容易成為標準,他有自己的瀏覽器,這很重要。


未來有兩個含義,一個是「未來標準」,一個是「未來最具主宰地位的框架」。

要說未來標準,那肯定只有Web Component有希望,React/Angular/Vue因為其背後的開發者背景是絕對不會成為標準的。Web上的標準有一個缺點,就是制定標準的人不是開發Web應用的人,所以總是要比Web應用的需求慢一拍,一些需要被React/Angular/Vue滿足了,標準才剛起步,所以,就算Web Component成為「未來標準」,也很可能沒人鳥他。

當然,不能說Web Component沒有前途,至少Google除了Angular之外也在推進Web Component,Youtube就採用的是適應Web Component的Polymer。

至於「未來最具主宰地位的框架」,我覺得還是三足鼎立,因為React背後的Facebook、Angular後面的Google還有Vue後面的開源社區,都不會放棄的。

要我說多一些選擇挺好,技術這東西不需要壟斷,各自按照自己的特點進化下去,因為各有特點,開發者可以根據自己應用的特點去選擇。


Facebook剛剛發布了ReactVR

引用 Merrick Christensen 今天發布的一條推文:

React的目標不是成為Web的什麼標準,而是為所有平台的界面開發提供一種統一的語言介面。React做到了真正的Learn once, write everywhere!

我不知道Web Component 或 React、Angular、Vue 誰可以代表未來,但我知道React還可以在通往未來的路上走得更遠,React屏蔽了所有平台底層的差異,抽象之後用同一種語言來描述界面,這樣開發者就可以真正專註於界面開發,並且不止局限於瀏覽器,而是將你的能力拓寬到所有的領域和平台,成為真正的「大前端」。


不知道你說的是初音未來還是栗山未來……

好吧,裝傻是不對的。

不過標準是標準,框架是框架,至於未來……當然是未來要流行的框架代表未來了。至於未來要流行的框架……

哎嘿?


R,A,V都不會成為標準。

前端框架進化太快,估計沒多久又有新的出來了。

大家都喜新厭舊的人(就是懶的寫那麼多代碼)


我沒見過哪個第三方框架會成為W3C標準的,組件化這思想20年前微軟就已經提出了,當時微軟把HTC/HTA、ActiveX和VML提交給W3C希望成為標準,但都被W3C拒絕了。只有Adobe的SVG不知道什麼原因被W3C接受了成為了標準。

這個問題的答案很明顯,Web Component因為是W3C的親兒子,不用說未來,現在就已經成為標準了。其餘幾個框架,又沒有提交W3C做標準的打算,未來不會成為標準的。所以問題的答案是Web Component。


不管是誰成為主流,都是需要符合開發者的味口,那就是文檔足夠豐富,使用足夠簡單,能滿足大多數使用場景,反觀現在的技術棧,有些還是太複雜了,各種腳手架,框架,包管理,並沒有像大家預想的那樣。最終還是會 分久必合,出現一個足夠優秀的技術框架,就像當年的jquery。


JSX這東西,我真的覺得是反人類的設計。縱觀andriod,ios,win,mac上面這些原生應用開發,哪個會把ui邏輯代碼和ui描述混在一起,都是GUI開發,面臨的ui問題都大同小異,為什麼他們沒有用JSX那種方式解決ui問題?你覺得那些開發人員都是吃乾飯的嗎?還想著JSX能被瀏覽器底層實現,有點異想天開了。


對初學者的我,個人還是比較喜歡react,組件分明,就是實現的過程有點麻煩,感覺依賴太多了,很多想用的插件都不健全


共存


恕我無知,React 不就是(使用) webComponent(的概念) 嗎?


推薦閱讀:

現在(2017年)是否還有必要學習jQuery?
在Redux中,應該把邏輯放在action creator里,還是分散在reducer里?
如何評價微軟開源的ReactXP?
如何評價 Facebook開源的 YOGA?
網上都說操作真實 DOM 慢,但測試結果卻比 React 更快,為什麼?

TAG:前端開發 | JavaScript | React | WebComponents |