深度解讀當代前端架構演進與趨勢(上)

軟件架構的核心思想,就是推斷軟件系統各個組件之間數據流動的方式。軟件架構的質量取決於你設法推斷這些數據流的難易程度!本文要講的內容,就是在今天的Web應用程序背後探索這些數據流和最終的體系結構。Web應用已從簡單的靜態網站(雙層結構)發展爲複雜的多層次、SPA和SSR驅動的API優先系統。CMS系統已發展成無頭(Headless)和內容優先的系統。

近年來,前端社區的面貌日新月異。早年流行的是jQuery引入的DOM注入算法,其很快被基於MVC的Backbone.js所取代。之後一夜之間,我們就身陷於雙向和單向數據流架構的叢林之中。我們的成長足跡在某處中斷了。曾幾何時沉浸在MVC的世界是如何突然進入React開創的單向數據流時代的?它們之間有什麼聯繫?隨着本文展開,我們將嘗試解開這個難題。

雖然本文針對的是前端工程師,但想要從宏觀層面理解現代Web應用程序架構的Web開發人員都能從本文中獲益。軟件體系背後有着大量活動——流程、需求收集、部署拓撲、技術棧等等。但那些已經超出了本文所涉及的範圍。

必要的前置知識——什麼是計算機?

計算機是一種從用戶收集數據/信息,並立刻或稍後將處理過的數據/信息提供給用戶的機器。計算機如何收集和展示這些數據呢?它使用軟件應用來實現這一目的。

軟件架構的關鍵是提供合理的手段來組成軟件,同時保持一切井然有序。

這裏的關鍵在於,軟件應用正在處理的數據被稱爲模型應用程序狀態。一些勇士可能將其稱爲應用程序的域模型業務邏輯。應用程序可以是桌面端也可以是Web端。

本文的宗旨是探索向(Web前端的)用戶表示這種應用程序狀態的合理方式,同時讓一切井然有序。我們將探索數據如何從模型流向視圖層,僅此而已。

經典MVC——起源

將數據與表示分離是(Web端和桌面端)圖形用戶界面的核心思想。對於MVC——模型-視圖-控制器來說,將表示(視圖)與關注域(模型)分離是其主導的設計理念。毫無疑問,MVC是一項開創性的成果,其影響力綿遠流長。

如果要爲軟件開發寫出第一原則,那麼它就會是SoC——關注點分離。而且MVC模式可能是它第一個真正的落地實踐。

MVC是爲Smalltalk-80語言推出的。在MVC中,視圖(View)對象顯示模型(Model)對象持有的數據。在我們全面研究MVC中的數據流之前,我們必須瞭解當時(約20世紀70年代)的軟件應用環境:

  • 這個MVC僅適用於桌面應用。那時離Web誕生還有幾十年的時間。
  • 沒有Web,複雜的GUI驅動的操作系統也不存在。
  • 這意味着應用軟件非常接近底層硬件。

以上這些限制對MVC影響很大。於是需要由控制器(Controller)對象負責響應鍵盤或鼠標等用戶輸入並轉換爲模型上的操作。此外,操作系統缺少GUI小部件意味着視圖與屏幕內容無法對應。

相反,視圖和控制器以配對的形式結合在一起。其中視圖部分向用戶顯示輸出內容,控制器部分接收來自用戶的輸入。應該注意的是,屏幕上的每個控件都有一個視圖——控制器配對,這也是小部件(widget)理念的雛形。

今天,在React、Vue或Angular中,這種視圖——控制器配對與組件的思想是一樣的,儘管狀態處理層面的具體機制有所不同。

關於MVC就介紹到這裏,下面的圖片展示了MVC中的數據流示例。在這個例子中,我們有一個帶遞增和遞減按鈕的簡單計數器。計數器狀態維持着模型。此外,我們把兩個按鈕簡化成了一個來簡化敘述。

經典MVC

在協作方面:

  1. 視圖控制器包含對模型的直接引用,但反過來不行。這意味着模型不依賴UI,可以在不擔心UI問題的前提下做更改。
  2. 模型實現了觀察者(Observer)模式,被一個或多個視圖對象註冊(subscribe)。當模型更改時會觸發事件,事件響應後視圖也會更新。

MVC中有兩條數據流。在視圖流中不涉及模型,只涉及UI的更改。顯示按鈕單擊效果或對鼠標滾動事件作出響應就是視圖流的例子。

MVC中的數據週期

今天我們不再使用這個MVC了,它有時被稱爲經典MVC老爹的MVC

開始使用應用程序模型

人們很快就意識到應用程序狀態無法與GUI完全隔離。我們總是要維護某種表示邏輯視圖狀態

複雜的圖形界面需要額外的狀態,這些狀態只用來輔助UI小部件,實現更好的用戶體驗。

但這可能會導致一些問題。來看看之前的計數器示例。當計數器達到10時,我們必須將標籤的顏色從黑色更改爲紅色以表示警告。這種顏色變化行爲實際上不是業務邏輯或關注點。這是純粹的美學部分(用戶體驗),需要加進來。真正的問題是——放在哪裏?是模型還是視圖

由於這種表示邏輯視圖狀態基本上是從域模型派生的狀態,因此必須在模型對象中維護它。但是域模型又要維護視覺部分(比如說紅色),這種定義就很尷尬。如果我們將它放在視圖對象中,那麼它會引入另一組問題。我們的標籤小部件不再是通用的了,無法在其他地方複用。此外,在視圖對象中放一個帶有硬編碼數字10的條件,意味着我們正在泄漏某些業務邏輯。

爲了解決這個問題,我們在原始的MVC中添加了另一個實體——應用程序模型(Application Model,AM)。有了AM以後,視圖——控制器配對不再直接訪問模型了。相反,它們向AM事件註冊並使用它來訪問所需的數據。

應用程序模型MVC

數據流和經典MVC是一樣的。當然,每種模式都有其優點和缺點,AM-MVC也不例外。最突出的問題是AM沒有對視圖對象的直接引用,因此即使AM被設計爲維持視圖狀態,也無法直接操作後者。

總的來說,引入應用程序模型會使視圖特定的狀態遠離域層,並降低了視圖對象的複雜性來簡化視圖對象。這和表示模型(Presentation Model)很像,這是Martin Fowler在其開創性研究中創造的概念:

表示模型的本質是一個完全自包含的類,它表示UI窗口的所有數據和行爲,但沒有任何用於在屏幕上渲染該UI的控件。視圖只是將表示模型的狀態顯示在屏幕上。

現代桌面架構的時代

時光飛逝,世界也在不斷變化,新一代操作系統開始展現威力。應用程序遠離了底層硬件,它們之間加入了完整的內核、OS驅動程序和實用程序。像Windows這樣基於GUI的操作系統提供了開箱即用的UI小部件。

不再需要控制器來監聽輸入設備了。視圖對象的理念改變了。

控制器的大多數功能都由操作系統接手。視圖的理念發生了變化:之前它只是一個小部件,現在它是一個衆多小部件的組合;一個視圖可以包含另一個視圖。視圖在某種意義上變成了雙向的,它響應用戶操作並顯示模型數據。

前端世界中視圖的理念與這個概念非常相似。在Web環境中,視圖是一個完整的頁面。

經典MVC變得過時且難用。爲了適應這些不斷變化的環境,Dolphin團隊在1995年正在尋找一種創建用戶界面的新模型。Dolphin團隊如何找出新設計的歷史可以參閱這裏這裏的記錄,本文不再贅述。

總而言之,該團隊最終將MVC模型旋轉了60度,他們稱其爲Twisting the triad。於是我們有了MVP。

在協作方面:

  1. 表示器(Presenter)監督表示邏輯。表示器可以直接更改視圖。視圖將用戶事件委派給表示器
  2. 根據實現,視圖註冊到模型上,並依賴表示器處理複雜邏輯;或者在其他情況下,視圖只依賴表示器處理一切。

正如Martin Fowler在關於GUI架構的論文中總結的那樣,他將MVP實現分爲監督控制器MVP被動視圖MVP。從圖中可以看出它們的差異和各自的數據流。

MVP——模型視圖表示器

MVVM——模型-視圖-視圖模型

MVP很棒,有許多可能的變種和複雜的細節;但從前端應用程序的角度來看,MVVM確實更勝一籌。在一些實現中,後者也被稱爲模型-視圖-綁定器。MVVM很像被動視圖MVP,但增加了數據綁定的功能。它是一種編程技術,將來自提供者和消費者的數據源綁定在一起並同步。它擺脫了我們過去需要用來保持視圖和模型同步的許多樣板代碼。這樣我們就能在高得多的抽象級別上工作了。在協作方面:

  1. 視圖模型(ViewModel)是一個對象,它公開視圖所使用的可綁定屬性和方法。
  2. MVVM有額外的綁定器(Binder)實體,負責使視圖視圖模型保持同步。每次視圖模型上的屬性更改時,視圖都會自動更新以反映UI上的更改。

MVVM——Model View ViewModel

MVVM中的數據綁定已經成爲許多前端庫的基礎,包括Knockout、Angular、Vue.js和React等。

我們將在Web應用程序部分再討論數據綁定。

進入Web應用程序領域

就像原始的MVC模式一樣,出現了一種用於Web應用程序的模式。它被稱爲Web MVC。實際上,Web應用程序的構建和部署方式讓MVC在Web端比在桌面端更加順其自然。

社區的主要困惑是不知道桌面MVCWeb MVC是兩種不同的模式。要是Web MVC當初不叫這個名字,大家就會清楚多了。

Web應用程序是分佈式應用程序的子類別。雖然MVC對Web應用程序感覺更自然一些,但一般來說構建分佈式應用程序是很困難的。代碼的某些部分在服務器上運行,同時還要保留在客戶端(例如瀏覽器)上。

大規模Web應用程序架構的重點在於確定代碼的哪個部分應該在哪裏執行。我們有服務端驅動的應用程序或富客戶端驅動的應用程序。在兩者之間,我們可以無限自由組合。

在MVC的語境中討論Web應用程序時有三個不同的數據週期,因此有三個MVC實現:服務端MVC、瀏覽器內部的MVC和前端MVC。瀏覽器負責三種類型交互的中介:

  1. 在客戶端(JS+HTML)代碼和服務端代碼之間。
  2. 在用戶和服務端代碼之間。
  3. 在用戶和客戶端代碼之間。

瀏覽器有自己的模型、視圖控制器。作爲開發人員,我們不必擔心瀏覽器MVC。

服務端MVC,亦即2號模型

服務端MVC的第一個衆所周知的實現是Sun Microsystems針對Java Web應用程序的2號模型(Model 2)

服務端MVC——前端視角

這個MVC與傳統的MVC非常相似,但由於數據跨越客戶端和服務端邊界時數據流週期時間呈指數級上升,因此前者多出來很多複雜性。需要注意的一些事項有:

  • 桌面MVC有兩個數據週期,而Web MVC有三個數據週期
  • 有兩種視圖週期。首先是客戶端視圖週期,例如滾動事件、鍵盤輸入等。其次是服務端視圖週期,例如頁面刷新、超鏈接激活等。
  • 最後我們有一個模型週期,它在通過客戶端-服務端邊界時有額外的時間複雜度。
  • 前端控制器(Front Controller):是通常由底層技術棧提供的組件,用於處理HTTP請求調度。例如Java Web應用程序中的Servlet容器、ASP.NET中的IHttpHandler或Node.js中的HTTP.Server類

今天的SSR——服務端渲染則是完全不同的概念。然而事實並非如此。由於整個HTML/內容是由服務端生成的,並且不涉及客戶端JavaScript代碼,因此完全使用服務端MVC構建的Web應用程序仍被視爲SSR。

超越服務端

從這裏開始就有意思了。不知不覺中,幾乎所有瀏覽器都開始提供JavaScript引擎。在我看來正是AJAX改變了Web應用程序。谷歌是最早的實踐者,在其郵件客戶端和地圖應用中採用了這項技術。

這個世界裏由服務端MVC生成HTML+JavaScript。JS代碼遍佈所有頁面。JavaScript主要用來減少服務端視圖週期以改善用戶體驗。表單提交、輸入驗證等內容由客戶端代碼處理。

客戶端有了自己的模型會發生什麼?

它是Web應用程序歷史上最流行的架構。大多數B2C應用程序、SEO友好網站,尤其是使用CMS(內容管理系統)構建的網站都在使用它。客戶端代碼量取決於應用程序的需求。

這樣的架構從未真正標準化,因此沒有名稱。它一直在漸進發展,仍被認爲是Web MVC的擴展。ASP.NET MVC、Java Struts、Python Django、Ruby ROR和PHP CodeIgniter是流行框架的一些例子,它們大量使用服務端MVCWeb MVC

當然,這種標準模式還有很多變體,但它們對當代前端架構沒有任何實際影響,可以忽略。

基礎RIA——富互聯網應用架構

瞭解過這些背景,我們現在準備討論當代前端架構。當代前端架構主要解決的是構建RIA——富互聯網應用程序的問題。RIA的確切定義並不存在,因爲很多事物都能用它描述。但總的來說,RIA富Web應用是應用程序的一個類別,其中應用程序嚴重依賴客戶端代碼,並且它們的用戶體驗非常接近桌面應用程序。它主要使用支持SPA(單頁面應用程序)的框架構建。來自Web MVC的服務端視圖週期的數據流這裏不存在。它通常只有一個初始HTML頁面,然後使用客戶端代碼和路由解決方案來渲染後續頁面。

構建RIA是一項複雜的操作,這種操作從以前基於桌面的GUI架構學習發展而來。視圖模型、觀察者、組件等就是從這些架構中借用的一些理念。Oliver steel在他15年前的博客文章中(相信我,它是最出色的文章之一),爲理解RIA數據流提供了很好的參考架構。

客戶端變重了——SPA的時代

RIA參考架構和Web MVC之間最顯著的區別是前者的頂層架構中缺少控制器視圖。然而字面意義上講它們並沒有消失。如果我們看一下底層,控制器和視圖仍然存在,只是承擔的角色大大縮減了。後端主要是API驅動的。視圖僅限於生成JSON,控制器負責編排傳入請求並將其映射到適當的業務工作流。

GUI模式很難?

如果你已經深入探索了前面的模式,那麼你將意識到GUI模式與其他軟件工程模式有所不同。以可複用的面向對象軟件的元素爲例:大多數模式都獨立於技術或語言,但GUI模式並非如此。這些模式適用於人機交互的邊界。用戶副作用本質上是模式的一部分。(注意:可複用的面向對象軟件的元素已經指出了經典MVC的本質)

GUI模式適用於HCI——人機交互的邊界。用戶和副作用本質上是模式的一部分。

因此,在不考慮基礎框架或語言的情況下幾乎不可能在理論上討論它們。到目前爲止,我們可以在相當高的抽象級別上探索這些模式。但當我們接近本文的核心時,我們將依靠不同的庫或框架來描述這些模式。

大多數Web UI模式可以分爲三個階段,即進化、變革和當代階段。

前端圖譜——宏觀視角

進化模式只是服務端MVC的擴展。它們並不會試圖改變方向或發明全新的事物。它們會一步一步地改進來補足現有應用程序的缺陷。而變革模式是將前端應用開發與服務端驅動的工作流程分離的那些理念。它們的到來標誌着SPA應用的興起。當代模式就是對這些變革模式的二次修正,也是前端社區前進的大方向。

DOM注入算法

由jQuery引入和掌握的這項技術是編寫大規模客戶端應用程序的真正起步,儘管jQuery並未真正解決架構問題。它旨在簡化當瀏覽器中存在太多不一致時的DOM操作。它提供了與瀏覽器無關的API。

雖然我不覺得這是有意爲之,但jQuery把DOM API簡化到了很難將其與正常的語言API區分的程度。這反過來又讓開發人員將DOM API(視圖層)與業務邏輯(模型)完美地混合在一起。

需要指出的一點是,它仍然在同一服務端MVC的上下文中。這只是一個擴展。沒有真正的控制反轉。視圖/頁面的總體控制仍然由服務端代碼驅動。

jQuery——HTML代碼

jQuery——DOM注入算法

在上面的代碼片段中,模型視圖表示器/控制器被混合成一個單體代碼結構。當模型只包含一個屬性時就是這種情況。想象一下,嘗試構建一個沒有服務端視圖週期的Web應用程序(比如SPA),做這樣的事情是沒有意義的。與DOM交互的代碼簡潔地注入了其他應用程序邏輯,這就是爲什麼它被稱爲DOM注入算法(注意:我不確定DOM注入這個術語是不是什麼規範名稱)

Backbone.js——MV*

正如我們在jQuery中看到的那樣,在開發應用程序時顯然缺少構建和組織代碼的方法。於是Backbone.js應運而生,成爲了新的進化解決方案。它是首批將MVC風格帶給客戶端的庫之一。

Backbone.js數據流

我們看一看Backbone數據流示意圖,就可以清楚地看到模型視圖,但是沒有控制器的等效對象。模式在不斷髮展,客戶端MVC只是之前MVC架構的進化。在這個進化過程中,大多數JavaScript社區都同意模型視圖的定義,但針對控制器沒有形成共識。考慮到客戶端環境,控制器的理念並不合適。控制器留待進一步解釋。

至於Backbone而言,控制器不存在;那麼它適合哪裏?是MVC、MVP還是MVVM? 借用服務端MVC的定義,控制器有兩個職責:以傳入的HTTP請求的形式響應用戶操作,並協調模型以生成視圖(HTML頁面)。在Backbone的情況下,視圖路由器共享這些職責,但是缺少獨立的控制器表示器的概念。

一些開發人員認爲Backbone是MVP,其中視圖類似於表示器,模板(Template)是視圖,而Backbone模型集合(Collection)構成模型

正如Addy Osmani在他的博客中所說,最好不要強行把Backbone歸類到任何特定的設計模式。設計模式應被視爲應用程序結構的靈活指南,由此看來Backbone既不像MVC也不像MVP。相反,它借鑑了多種架構模式中的一些最佳概念,並創建了一個運行良好的靈活框架。

這就是MV模型-視圖-其他*的誕生歷程。強烈推薦Addy Osmani的博客文章:理解MVC和MVP——適合JavaScript和Backbone開發人員

與之前的jQuery相比,Backbone可以生成更加結構化的代碼。

Backbone.js中的視圖模板

在Backbone.js中創建一個模型

在Backbone.js中創建一個視圖實例

在Backbone.js中鏈接視圖和模型

前文中我將Backbone稱爲下一個進化解決方案。原因是它只是補充並擴展了服務端MVC。例如,如果我們的後端是RESTful,意味着前端代碼只是用來表示服務端模型的手段,那麼Backbone已預置爲與API同步:

Backbone.js中自動生成的集合方法

而且Backbone中還有許多其他小型約定,感覺只是擴展而已。總之,Backbone可能不是當時唯一的解決方案,但它在代碼結構和組織領域確實做出了開創性的工作。像jQuery一樣,它被許多產品採用。

Knockout.js——前端的數據綁定

Knockout.js是我們基本模式的最後一個案例。它旨在爲JavaScript實現MVVM——模型-視圖-視圖模型。它也確實做到了。Backbone解決的是代碼組織和結構的問題,而Knockout是在聲明式數據綁定的幫助下有效地實現視圖層。聲明式綁定的優點與其他聲明式編程結構相同:

  1. 易讀:聲明式代碼易於編程
  2. 減少樣板:綁定允許我們在視圖模型更改時自動更新DOM,並在視圖通過用戶輸入更改時更新視圖模型
  3. 可觀察:Knockout在事件之上提供更高級別的抽象。這允許Knockout自動跟蹤視圖模型props之間的依賴項。如果需要,我們可以註冊可觀察屬性。

Knockout.js視圖——雙向綁定

Knockout.js中的視圖模型——使用計算屬性響應

雖然Knockout爲視圖視圖模型提供了定義良好的結構,但卻沒關注應用程序模型的問題。這使得Knockout高度專注、可以廣泛適應,因爲它可以用作庫而非框架。我見過有人用它構建迷你SPA應用程序,其中Web應用程序有多個頁面,每個頁面都是一個小型的Knockout應用。這個StackOverflow答案清楚地定義了Knockout的MVVM實現的範圍。

通常假設Knockout模型駐留在服務端。視圖模型只是使用Ajax或等效方式詢問服務端模型。

它在DOM更新用途上取代了jQuery和像Handlebars這樣的模板解決方案,但仍然使用jQuery來製作動畫、Ajax等實用程序。與Backbone結合後,它可以作爲MVVM模式的完整實現。理論上講這可能已成事實,但在此之前,這些概念已經被下一代工具鏈吸納過去了。

接下來Angular 1、Aurelia、Ember.js等代表的變革旅程開始了。

由於它與.NET世界緊密相關,因此被廣泛用於ASP.NET MVC應用程序中。像Backbone一樣,它是另一種進化解決方案,針對的是稍微不一樣的問題。而且客戶端代碼依舊只是服務端MVC模式的擴展。服務端仍然是主導架構。彼時Backbone和Knockout常被拿來對比,但實際上它們是免費的解決方案。

KnockoutBackbone都是JavaScript庫。不知何故,Backbone被視爲一個框架。爲什麼?這裏沒有確定的答案,但可能是因爲視角不同。由於強調代碼結構,Backbone始終採用更高級別的抽象處理。此外,Backbone從沒想過要取代無處不在的jQuery(即使在2019年,最流行的100萬個網站中有7成都在使用jQuery),而Knockout與核心jQuery功能高度重合(比如DOM操作),這自然讓Knockout舉步維艱。因此與Backbone相比,Knockout的應用被大大侷限了。但它仍然是前端社區首批實現的聲明式數據綁定之一,值得在這裏專門提到它。

Angular 1——給我控制權

jQuery對DOM意味着什麼,Angular 1就對一般意義的前端生態系統有着同樣的影響。它永久改變了構建大規模客戶端應用程序的概念。作爲一個框架,它引入了許多概念——模塊系統、依賴注入、控制反轉和更簡單的數據綁定等。

曾幾何時,選擇正確的JavaScript庫併爲前端構建完美的技術棧仍然是一件痛苦的事。Angular 1提供了一種更簡單但有凝聚力的替代方案。Ember.js和其他類似的框架也可以這麼說,但是Angular 1的普及度是完全不同的層面,稱得上是那個時代的選擇。。

從某種意義上說Angular 1是變革解決方案,它不再是對服務端MVC的簡單擴展,而是在頁面上灑滿了客戶端代碼。Angular 1使SPA成爲構建下一代用戶體驗的幾乎是事實上的一流解決方案。

是框架還是庫?

先前的解決方案更像是庫而不是框架。毫無疑問,Angular 1是一個明確定義的框架。框架和庫之間的關鍵區別是IOC——控制反轉。作爲框架,Angular 1具備:

  1. 明確定義的MVVM:Angular 1具有清晰的模型視圖視圖模型對象。
  2. 依賴注入(DI):Angular 1對DI提供一流支持,爲模型對象提供生命週期管理。在Angular 1中,應用程序的模型使用服務(Service)實現。默認情況下服務是一個單例實體,對於模型對象來說通常很理想。
  3. 數據綁定和更改檢測:數據綁定是聲明式的,更改檢測是自動的。數據綁定是MVVM必要的組件。綁定是雙向的。此外更改檢測幾乎是自動的(Angular 1真的很神奇)。它爲開發人員省去了許多樣板代碼。事件的使用和整體註冊機制往往也會簡化。這在基於MVC的系統中非常普遍。事件還會降低代碼可讀性,因爲某些工作流的數據流分佈在代碼中。
  4. 模塊系統:Angular 1引入了特定於框架的模塊系統。模塊是幾乎所有語言的代碼組織的基礎。JavaScript直到2015年纔有模塊系統(瀏覽器直到2018年才支持它)。Angular在組織方面領先時代。

與此同時,Angular 1也因其引入的複雜性而受到批評。最重要的批評指出它是在服務端構造之後建模的。前端開發人員並不習慣這樣。有些缺陷無法忽視:

  1. 命名空間衝突:雖然DI很棒,但它是使用全局命名空間的Service Locator模式實現的,於是服務必須添加前綴。
  2. 雙向數據綁定:當時這可能是個好主意,但之後人們意識到它並不能真正擴展。特別是React的興起使雙向數據綁定成爲可選項。不小心的話,雙向綁定可以帶來許多面條代碼。
  3. 令人困惑的術語:Angular 1使用的一些術語顯然令人困惑。例如,Angular 1用$scope作爲視圖模型,但它也有控制器可以擴充$scope對象。可能正確的名稱可以是VMFactory之類。此外,Angular 1有三種服務配方,其中一種名爲Service

還有許多其他小問題。另外,Angular 2或簡稱Angular是一個徹底的更新,它就像一個全新的框架。除了名字和少量概念之外,兩代版本之間找不到什麼共同點。

Angular.js——概覽

多年來,Angular 1發佈了一些小版本更新,修復了許多複雜的小細節。最重要的是增加了組件模型,組件模型是前端世界大多數理念的交匯點。

Angular 1在前端社區的遺產影響深遠。它的優缺點幫助社區瞭解了軟件架構的重要性,併爲編寫可擴展應用程序的工作提供了基準。它的缺點/不足成爲了未來架構解決問題的基礎。

原文鏈接
https://blog.webf.zone/contemporary-front-end-architectures-fb5b500b0231

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章