内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

軟件架構(gòu)之如何理解前后端分離與前端模塊化

這篇文章主要講解了“軟件架構(gòu)之如何理解前后端分離與前端模塊化”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“軟件架構(gòu)之如何理解前后端分離與前端模塊化”吧!

創(chuàng)新互聯(lián)建站是一家專(zhuān)注于成都做網(wǎng)站、網(wǎng)站制作與策劃設(shè)計(jì),張掖網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專(zhuān)注于網(wǎng)站建設(shè)10年,網(wǎng)設(shè)計(jì)領(lǐng)域的專(zhuān)業(yè)建站公司;建站業(yè)務(wù)涵蓋:張掖等地區(qū)。張掖做網(wǎng)站價(jià)格咨詢(xún):13518219792

前后端分離架構(gòu)

在正式說(shuō)明前后臺(tái)架構(gòu)分離之前,我們來(lái)看一下多年之前,傳統(tǒng)軟件開(kāi)發(fā)的架構(gòu)模式。

為什么要前后端分離

還記得零幾年我上大學(xué)的時(shí)候,在初學(xué) Java Web 開(kāi)發(fā)時(shí),課本上介紹的還是 JSP + Servlet  這種很傳統(tǒng)的架構(gòu)模式,這時(shí)候前端和后端業(yè)務(wù)邏輯代碼都在一個(gè)工程里面,還沒(méi)有分離開(kāi)來(lái),這種開(kāi)發(fā)模式屬于 Model1  模式,雖然實(shí)現(xiàn)了邏輯功能和顯示功能的分離,但是由于視圖層和控制層都是由 JSP 頁(yè)面實(shí)現(xiàn)的,即視圖層和控制層并沒(méi)有實(shí)現(xiàn)分離。

隨著學(xué)習(xí)的深入以及漸漸流行的企業(yè)應(yīng)用開(kāi)發(fā),我們漸漸的擯棄這種技術(shù)選型,并開(kāi)始在項(xiàng)目中使用了若干開(kāi)源框架,常用的框架組合有 Spring  +Struts/Spring MVC + Hibernate/Mybatis  等等,由于框架的優(yōu)越性以及良好的封裝性使得這套開(kāi)發(fā)框架組合迅速成為各個(gè)企業(yè)開(kāi)發(fā)中的不二之選,這些框架的出現(xiàn)也減少了開(kāi)發(fā)者的重復(fù)編碼工作,簡(jiǎn)化開(kāi)發(fā),加快開(kāi)發(fā)進(jìn)度,降低維護(hù)難度,隨之而火熱的是這套技術(shù)框架背后的開(kāi)發(fā)模式,即  MVC 開(kāi)發(fā)模式,它是為了克服 Model1 存在的不足而設(shè)計(jì)的。

MVC 的具體含義是:Model + View + Controller,即模型+視圖+控制器,

  • Model 模型層: 它常常使用 JavaBean  來(lái)編寫(xiě),它接受視圖層請(qǐng)求的數(shù)據(jù),然后進(jìn)行相應(yīng)的業(yè)務(wù)處理并返回最終的處理結(jié)果,它負(fù)擔(dān)的責(zé)任最為核心,并利用 JavaBean  具有的特性實(shí)現(xiàn)了代碼的重用和擴(kuò)展以及給維護(hù)帶來(lái)了方便。

  • View 視圖層: 代表和用戶交互的界面,負(fù)責(zé)數(shù)據(jù)的采集和展示,通常由 JSP 實(shí)現(xiàn)。

  • Controller 控制層:  控制層是從用戶端接收請(qǐng)求,然后將請(qǐng)求傳遞給模型層并告訴模型層應(yīng)該調(diào)用什么功能模塊來(lái)處理該請(qǐng)求,它將協(xié)調(diào)視圖層和模型層之間的工作,起到中間樞紐的作用,它一般交由  Servlet 來(lái)實(shí)現(xiàn)。

MVC的工作流程如下圖所示。

軟件架構(gòu)之如何理解前后端分離與前端模塊化

同時(shí),項(xiàng)目開(kāi)發(fā)在進(jìn)行模塊分層時(shí)也會(huì)劃分為三層:控制層,業(yè)務(wù)層,持久層??刂茖迂?fù)責(zé)接收參數(shù),調(diào)用相關(guān)業(yè)務(wù)層,封裝數(shù)據(jù),以及路由并將數(shù)據(jù)渲染到 JSP  頁(yè)面,然后在 JSP  頁(yè)面中將后臺(tái)的數(shù)據(jù)展現(xiàn)出來(lái),相信大家對(duì)這種開(kāi)發(fā)模式都十分熟悉,不管是企業(yè)開(kāi)發(fā)或者是個(gè)人項(xiàng)目的搭建,這種開(kāi)發(fā)模式都是大家的首選,不過(guò),隨著開(kāi)發(fā)團(tuán)隊(duì)的擴(kuò)大和項(xiàng)目架構(gòu)的不斷演進(jìn),這套開(kāi)發(fā)模式漸漸有些力不從心。

接下來(lái),我們來(lái)分析下這套開(kāi)發(fā)模式的痛點(diǎn)。

痛點(diǎn)一:JSP 效率問(wèn)題

首先,JSP 必須要在 Servlet 容器中運(yùn)行(例如 Tomcat,jetty 等),在請(qǐng)求 JSP 時(shí)也需要進(jìn)行一次編譯過(guò)程,最后被譯成 Java  類(lèi)和 class 文件,這些都會(huì)占用 PermGen 空間,同時(shí)也需要一個(gè)新的類(lèi)加載器加載,JSP 技術(shù)與 Java 語(yǔ)言和 Servlet  有強(qiáng)關(guān)聯(lián),在解耦上無(wú)法與模板引擎或者純 html 頁(yè)面相媲美。其次每次請(qǐng)求 JSP 后得到的響應(yīng)都是 Servlet 通過(guò)輸出流輸出的 html  頁(yè)面,效率上也沒(méi)有直接使用 html 高。由于 JSP 與 Servlet 容器的強(qiáng)關(guān)聯(lián),在項(xiàng)目?jī)?yōu)化時(shí)也無(wú)法直接使用 Nginx 作為 JSP 的 web  服務(wù)器,性能提升不高。

痛點(diǎn)二:人員分工不明

在這種開(kāi)發(fā)模式下的工作流程通常是:設(shè)計(jì)人員給出頁(yè)面原型設(shè)計(jì)后,前端工程師只負(fù)責(zé)將設(shè)計(jì)圖切成 html 頁(yè)面,之后則需要由后端開(kāi)發(fā)工程師來(lái)將 html 轉(zhuǎn)為  JSP  頁(yè)面進(jìn)行邏輯處理和數(shù)據(jù)展示。在這種工作模式下,人為出錯(cuò)率較高,后端開(kāi)發(fā)人員任務(wù)更重,修改問(wèn)題時(shí)需要雙方協(xié)同開(kāi)發(fā),效率低下,一旦出現(xiàn)問(wèn)題后,前端開(kāi)發(fā)人員面對(duì)的是充滿標(biāo)簽和表達(dá)式的  JSP 頁(yè)面,后端人員在面對(duì)樣式或者交互的問(wèn)題時(shí)本就造詣不高的前端技術(shù)也會(huì)捉襟見(jiàn)肘。

在某些緊急情況下也會(huì)出現(xiàn)前端人員調(diào)試后端代碼,后端開(kāi)發(fā)人員調(diào)試前端代碼這些讓人捧腹的現(xiàn)象,分工不明確,且溝通成本大,一旦某些功能需要返工則需要前后端開(kāi)發(fā)人員,這種情況下,對(duì)于前后端人員的后期技術(shù)成長(zhǎng)也不利,后端追求的是高并發(fā)、高可用、高性能、安全、架構(gòu)優(yōu)化等,前端追求的是模塊化、組件整合、速度流暢、兼容性、用戶體驗(yàn)等等,但是在  MVC 這種開(kāi)發(fā)模式下顯然會(huì)對(duì)這些技術(shù)人員都有一定的掣肘。

痛點(diǎn)三:不利于項(xiàng)目迭代

項(xiàng)目初期,為了快速上線應(yīng)用,選擇使用這種開(kāi)發(fā)模式來(lái)進(jìn)行 Java Web  項(xiàng)目的開(kāi)發(fā)是非常正確的選擇,此時(shí)流量不大,用戶量也不高,并不會(huì)有非??量痰男阅芤?,但是隨著項(xiàng)目的不斷成長(zhǎng),用戶量和請(qǐng)求壓力也會(huì)不斷擴(kuò)大,對(duì)于互聯(lián)網(wǎng)項(xiàng)目的性能要求是越來(lái)越高,如果此時(shí)的前后端模塊依舊耦合在一起是非常不利于后續(xù)擴(kuò)展的。舉例說(shuō)明一下,為了提高負(fù)載能力,我們會(huì)選擇做集群來(lái)分擔(dān)單個(gè)應(yīng)用的壓力,但是模塊的耦合會(huì)使得性能的優(yōu)化空間越來(lái)越低,因?yàn)閱蝹€(gè)項(xiàng)目會(huì)越來(lái)越大,不進(jìn)行合理的拆分無(wú)法做到最好的優(yōu)化,又或者在發(fā)版部署上線的時(shí)候,明明只改了后端的代碼,前端也需要重新發(fā)布,或者明明只改了部分頁(yè)面或者部分樣式,后端代碼也需要一起發(fā)布上線,這些都是耦合較嚴(yán)重時(shí)常見(jiàn)的不良現(xiàn)象,因此原始的前后端耦合在一起的架構(gòu)模式已經(jīng)逐漸不能滿足項(xiàng)目的演進(jìn)方向,需要需找一種解耦的方式替代當(dāng)前的開(kāi)發(fā)模式。

痛點(diǎn)四:不滿足業(yè)務(wù)需求

隨著公司業(yè)務(wù)的不斷發(fā)展,僅僅只有瀏覽器端的 Web 應(yīng)用已經(jīng)逐漸顯得有些不夠用了,目前又是移動(dòng)互聯(lián)網(wǎng)急劇增長(zhǎng)的時(shí)代,手機(jī)端的原生 App  應(yīng)用已經(jīng)非常成熟,隨著 App 軟件的大量普及越來(lái)越多的企業(yè)也加入到 App  軟件開(kāi)發(fā)當(dāng)中來(lái),為了盡可能的搶占商機(jī)和提升用戶體驗(yàn),你所在的公司可能也不會(huì)把所有的開(kāi)發(fā)資源都放在 web  應(yīng)用上,而是多端應(yīng)用同時(shí)開(kāi)發(fā),此時(shí)公司的業(yè)務(wù)線可能就是如下的幾種或者其中一部分:

軟件架構(gòu)之如何理解前后端分離與前端模塊化

瀏覽器端的 Web 應(yīng)用、iOS 原生 App、安卓端原生 App、微信小程序等等,可能只是開(kāi)發(fā)其中的一部分產(chǎn)品,但是除了 web 應(yīng)用能夠使用傳統(tǒng)的  MVC 模式開(kāi)發(fā)外,其他的都無(wú)法使用該模式進(jìn)行開(kāi)發(fā),像原生 App 或者微信小程序都是通過(guò)調(diào)用 RESTful api 的方式與后端進(jìn)行數(shù)據(jù)交互。

隨著互聯(lián)網(wǎng)技術(shù)的發(fā)展,更多的技術(shù)框架被提了出來(lái),其中最革命性的就是前后端分離概念的提出。

什么是前后端分離

何為前后端分離,我認(rèn)為應(yīng)該從以下幾個(gè)方面來(lái)理解。

前后端分離是一種項(xiàng)目開(kāi)發(fā)模式

當(dāng)業(yè)務(wù)變得越來(lái)越復(fù)雜或者產(chǎn)品線越來(lái)越多,原有的開(kāi)發(fā)模式已經(jīng)無(wú)法滿足業(yè)務(wù)需求,當(dāng)端上的產(chǎn)品越來(lái)越多,展現(xiàn)層的變化越來(lái)越快、越來(lái)越多,此時(shí)就應(yīng)該進(jìn)行前后端分離分層抽象,簡(jiǎn)化數(shù)據(jù)獲取過(guò)程,比如目前比較常用的就是前端人員自行實(shí)現(xiàn)跳轉(zhuǎn)邏輯和頁(yè)面交互,后端只負(fù)責(zé)提供接口數(shù)據(jù),二者之間通過(guò)調(diào)用  RESTful api 的方式來(lái)進(jìn)行數(shù)據(jù)交互,如下圖所示:

軟件架構(gòu)之如何理解前后端分離與前端模塊化

此時(shí)就不會(huì)出現(xiàn) HTML 代碼需要轉(zhuǎn)成 JSP  進(jìn)行開(kāi)發(fā)的情況,前端項(xiàng)目只負(fù)責(zé)前端部分,并不會(huì)摻雜任何后端代碼,這樣的話代碼不再耦合。同時(shí),前端項(xiàng)目與后端項(xiàng)目也不會(huì)再出現(xiàn)耦合嚴(yán)重的現(xiàn)象,只要前后端協(xié)商和定義好接口規(guī)范及數(shù)據(jù)交互規(guī)范,雙方就可以并行開(kāi)發(fā),互不干擾,業(yè)務(wù)也不會(huì)耦合,兩端只通過(guò)接口來(lái)進(jìn)行交互。

在 MVC  模式開(kāi)發(fā)項(xiàng)目時(shí),往往后端過(guò)重,“控制權(quán)”也比較大,既要負(fù)責(zé)處理業(yè)務(wù)邏輯、權(quán)限管理等后端操作,也需要處理頁(yè)面跳轉(zhuǎn)等邏輯,在前后端分離的模式中,后端由原來(lái)的大包大攬似的獨(dú)裁者變成了接口提供者,而前端也不僅僅是原來(lái)那樣僅處理小部分業(yè)務(wù),頁(yè)面跳轉(zhuǎn)也不再由后端來(lái)處理和決定,整個(gè)項(xiàng)目的控制權(quán)已經(jīng)由后端過(guò)渡至前端來(lái)掌控,前端需要處理的更多。

前端項(xiàng)目和后端項(xiàng)目隔離開(kāi)來(lái)、互不干涉,通過(guò)接口和數(shù)據(jù)規(guī)范來(lái)完成項(xiàng)目功能需求,這也是目前比較流行的一種開(kāi)發(fā)方式。

前后端分離是一種人員分工

在前后端分離的架構(gòu)模式下,后臺(tái)負(fù)責(zé)數(shù)據(jù)提供,前端負(fù)責(zé)顯示交互,在這種開(kāi)發(fā)模式下,前端開(kāi)發(fā)人員和后端開(kāi)發(fā)人員分工明確,職責(zé)劃分十分清晰,雙方各司其職,不會(huì)存在邊界不清晰的地方,并且從業(yè)人員也各司其職。

前端開(kāi)發(fā)人員包括 Web 開(kāi)發(fā)人員、原生 App 開(kāi)發(fā)人員,后端開(kāi)發(fā)則是指 Java 開(kāi)發(fā)人員(以 Java  語(yǔ)言為例),不同的開(kāi)發(fā)人員只需要注重自己所負(fù)責(zé)的項(xiàng)目即可。后端專(zhuān)注于控制層(RESTful API)、服務(wù)層 、數(shù)據(jù)訪問(wèn)層,前端專(zhuān)注于前端控制層、  視圖層,不會(huì)再出現(xiàn)前端人員需要維護(hù)部分后端代碼,或者后端開(kāi)發(fā)人員需要去調(diào)試樣式等等職責(zé)不清和前后端耦合的情況,我們通過(guò)兩張項(xiàng)目開(kāi)發(fā)流程簡(jiǎn)圖來(lái)對(duì)比:

軟件架構(gòu)之如何理解前后端分離與前端模塊化

此時(shí),開(kāi)發(fā)過(guò)程中會(huì)存在前后端耦合的情況,如果出現(xiàn)問(wèn)題前端需要返工、后端也需要返工,開(kāi)發(fā)效率會(huì)有所影響?,F(xiàn)在,前后端分離后流程簡(jiǎn)圖如下:

軟件架構(gòu)之如何理解前后端分離與前端模塊化

前后端分離后,服務(wù)器端開(kāi)發(fā)人員和前端開(kāi)發(fā)人員各干各的,大家互不干擾,。在設(shè)計(jì)完成后,Web 端開(kāi)發(fā)人員、App  端開(kāi)發(fā)人員、后端開(kāi)發(fā)人員都可以投入到開(kāi)發(fā)工作當(dāng)中,能夠做到并行開(kāi)發(fā),前端開(kāi)發(fā)人員與后端開(kāi)發(fā)人員職責(zé)分離,即使出現(xiàn)問(wèn)題,也是修復(fù)各自的問(wèn)題不會(huì)互相影響和耦合,開(kāi)發(fā)效率高且滿足企業(yè)對(duì)于多產(chǎn)品線的開(kāi)發(fā)需求。

前后端分離是一種架構(gòu)模式

前后端分離后,各端應(yīng)用可以獨(dú)立打包部署,并針對(duì)性的對(duì)部署方式進(jìn)行優(yōu)化,不再是前后端一個(gè)統(tǒng)一的工程最終打成一個(gè)部署包進(jìn)行部署。以 Web  應(yīng)用為例,前端項(xiàng)目部署后,不再依賴(lài)于 Servlet 容器,可以使用吞吐量更大的 Nginx  服務(wù)器,采用動(dòng)靜分離的部署方式,既提升了前端的訪問(wèn)體驗(yàn),也減輕了后端服務(wù)器的壓力,再進(jìn)一步優(yōu)化的話,可以使用頁(yè)面緩存、瀏覽器緩存等設(shè)置,也可以使用 cdn  等產(chǎn)品提升靜態(tài)資源的訪問(wèn)效率。對(duì)于后端服務(wù)而言,可以進(jìn)行集群部署提升服務(wù)的響應(yīng)效率,也可以進(jìn)一步的進(jìn)行服務(wù)化的拆分等等。前后端分離后的獨(dú)立部署維護(hù)以及針對(duì)性的優(yōu)化,可以加快整體響應(yīng)速度和吞吐量。

前端發(fā)展歷程

當(dāng)我們?nèi)チ私饽硞€(gè)事物的時(shí)候,首先我們需要去了解它的歷史,才能更好的把握它的未來(lái)。

原始時(shí)代

世界上第一款瀏覽器 NCSAMosaic  ,是網(wǎng)景公司(Netscape)在1994年開(kāi)發(fā)出來(lái)的,它的初衷是為了方便科研人員查閱資料、文檔(這個(gè)時(shí)候的文檔大多是圖片形式的)。那個(gè)時(shí)代的每一個(gè)交互,按鈕點(diǎn)擊、表單提交,都需要等待瀏覽器響應(yīng)很長(zhǎng)時(shí)間,然后重新下載一個(gè)新頁(yè)面。

同年 PHP(超文本預(yù)處理器) 腳本語(yǔ)言被開(kāi)發(fā)出來(lái),開(kāi)啟了數(shù)據(jù)嵌入模板的 MVC 模式,同時(shí)期比較類(lèi)似的做法有以下幾種:

  • PHP 直接將數(shù)據(jù)內(nèi)嵌到 HTML 中。

  • ASP 的 ASPX,在 HTML 中嵌入 C# 代碼。

  • Java 的 JSP 直接將數(shù)據(jù)嵌入到網(wǎng)頁(yè)中。

這個(gè)時(shí)期,瀏覽器的開(kāi)發(fā)者,以后臺(tái)開(kāi)發(fā)人員居多,大部分前后端開(kāi)發(fā)是一體的,大致開(kāi)發(fā)流程是:后端收到瀏覽器的請(qǐng)求 ---> 發(fā)送靜態(tài)頁(yè)面 --->  發(fā)送到瀏覽器。即使是有專(zhuān)門(mén)的前端開(kāi)發(fā),也只是用 HTML 寫(xiě)寫(xiě)頁(yè)面模板、CSS  給頁(yè)面排個(gè)好看點(diǎn)的版式。在這一時(shí)期,前端的作用有限,往往只是切圖仔的角色。

鐵器時(shí)代

1995年,網(wǎng)景公司的一位叫布蘭登·艾奇的大佬,希望開(kāi)發(fā)出一個(gè)類(lèi)似 Java  的腳本語(yǔ)言,用來(lái)提升瀏覽器的展示效果,增強(qiáng)動(dòng)態(tài)交互能力。結(jié)果大佬喝著啤酒抽著煙,十來(lái)天就把這個(gè)腳本語(yǔ)言寫(xiě)出來(lái)了,功能很強(qiáng)大,就是語(yǔ)法一點(diǎn)都不像  Java。這樣就漸漸形成了前端的雛形:HTML 為骨架,CSS 為外貌,JavaScript 為交互。

同時(shí)期微軟等一些公司也針對(duì)自家瀏覽器開(kāi)發(fā)出了自己的腳本語(yǔ)言。瀏覽器五花八門(mén),雖然有了比較統(tǒng)一的 ECMA  標(biāo)準(zhǔn),但是瀏覽器先于標(biāo)準(zhǔn)在市場(chǎng)上流行開(kāi)來(lái),成為了事實(shí)標(biāo)準(zhǔn)。導(dǎo)致,現(xiàn)在前端工程師還要在做一些政府古老項(xiàng)目的時(shí)候,還要去處理瀏覽器兼容(萬(wàn)惡的 IE  系列)。

不管怎么說(shuō),前端開(kāi)發(fā)也算是能寫(xiě)點(diǎn)邏輯代碼了,不再是只能畫(huà)畫(huà)頁(yè)面的低端開(kāi)發(fā)了。隨著1998年 AJax 的出現(xiàn),前端開(kāi)發(fā)從  Web1.0邁向了Web2.0,前端從純內(nèi)容的靜態(tài)展示,發(fā)展到了動(dòng)態(tài)網(wǎng)頁(yè),富交互,前端數(shù)據(jù)處理的新時(shí)期。這一時(shí)期,比較知名的兩個(gè)富交互動(dòng)態(tài)的瀏覽器產(chǎn)品是。

  • Gmail(2004年)

  • Google 地圖(2005年)

由于動(dòng)態(tài)交互、數(shù)據(jù)交互的需求增多,還衍生出了jQuery(2006) 這樣優(yōu)秀的跨瀏覽器的 js 工具庫(kù),主要用于 DOM  操作,數(shù)據(jù)交互。有些古老的項(xiàng)目,甚至近幾年開(kāi)發(fā)的大型項(xiàng)目現(xiàn)在還在使用 jQuery,以至于 jQuery 庫(kù)現(xiàn)在還在更新,雖然體量上已經(jīng)遠(yuǎn)遠(yuǎn)不及  React、Vue 這些優(yōu)秀的前端庫(kù)。

信息時(shí)代

自 2003  以后,前端發(fā)展渡過(guò)了一段比較平穩(wěn)的時(shí)期,各大瀏覽器廠商除了按部就班的更新自己的瀏覽器產(chǎn)品之外,沒(méi)有再作妖搞點(diǎn)其他事情。但是我們程序員們耐不住寂寞啊,工業(yè)化推動(dòng)了信息化的快速到來(lái),瀏覽器呈現(xiàn)的數(shù)據(jù)量越來(lái)越大,網(wǎng)頁(yè)動(dòng)態(tài)交互的需求越來(lái)越多,JavaScript  通過(guò)操作 DOM  的弊端和瓶頸越來(lái)越明顯(頻繁的交互操作,導(dǎo)致頁(yè)面會(huì)很卡頓),僅僅從代碼層面去提升頁(yè)面性能,變得越來(lái)越難。于是優(yōu)秀的大佬們又干了點(diǎn)驚天動(dòng)地的小事兒:

  • 2008 年,谷歌 V8 引擎發(fā)布,終結(jié)微軟 IE 時(shí)代。

  • 2009 年 AngularJS 誕生、Node誕生。

  • 2011 年 ReactJS 誕生。

  • 2014 年 VueJS 誕生。

其中,V8 和 Node.JS  的出現(xiàn),使前端開(kāi)發(fā)人員可以用熟悉的語(yǔ)法糖編寫(xiě)后臺(tái)系統(tǒng),為前端提供了使用同一語(yǔ)言的實(shí)現(xiàn)全棧開(kāi)發(fā)的機(jī)會(huì)(JavaScript不再是一個(gè)被嘲笑只能寫(xiě)寫(xiě)頁(yè)面交互的腳本語(yǔ)言)。React、Angular、Vue  等 MVVM 前端框架的出現(xiàn),使前端實(shí)現(xiàn)了項(xiàng)目真正的應(yīng)用化(SPA單頁(yè)面應(yīng)用),不再依賴(lài)后臺(tái)開(kāi)發(fā)人員處理頁(yè)面路由  Controller,實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)的自我管理。同時(shí)也推動(dòng)了前后端的徹底分離(前端項(xiàng)目獨(dú)立部署,不再依賴(lài)類(lèi)似的 template 文件目錄)。

至于為啥 MVVM 框架能提升前端的渲染性能,這里簡(jiǎn)單的說(shuō)一下原理,因?yàn)榇罅康?DOM  操作是性能瓶頸的罪魁禍?zhǔn)祝峭ㄟ^(guò)一定的分析比較算法,實(shí)現(xiàn)同等效果下的最小 DOM 開(kāi)銷(xiāo)是可行的。React、Vue  這類(lèi)框架大都是通過(guò)這類(lèi)思想實(shí)現(xiàn)的,具體實(shí)現(xiàn)可以去看一下相關(guān)資料。前后端分離也導(dǎo)致前端的分工發(fā)生了一些變化。

軟件架構(gòu)之如何理解前后端分離與前端模塊化

而后端開(kāi)發(fā)更加關(guān)注數(shù)據(jù)服務(wù),前端則負(fù)責(zé)展示和交互。當(dāng)然相應(yīng)的學(xué)習(xí)成本也越來(lái)越大,Node.JS的出現(xiàn)也使得前端前后端一起開(kāi)發(fā)成為可能,好多大公司在  2015 年前后就進(jìn)行了嘗試,用 Node.JS 作為中間數(shù)據(jù)轉(zhuǎn)接層,讓后端更加專(zhuān)注于數(shù)據(jù)服務(wù)和治理。

前端模塊化發(fā)展歷程

自 2009 年 5 月 Node.js 發(fā)布以來(lái),前端能干的事情越來(lái)越多。短短 10  來(lái)年的時(shí)間,前端便從刀耕火種的年代走向了模塊化、工程化的時(shí)代。各種前端框架百家爭(zhēng)鳴,前端贏來(lái)了真正屬于自己的時(shí)代。

原始時(shí)代

時(shí)間回到  2009年,記得那時(shí)候還沒(méi)有流行前后端分離,很多項(xiàng)目還是混在一起,而那時(shí)候的前端開(kāi)發(fā)人員大多數(shù)也都是“切圖仔”。前端完成靜態(tài)頁(yè)面,由服務(wù)端同事完成數(shù)據(jù)的嵌入,也就是所謂的套頁(yè)面操作,每當(dāng)有類(lèi)似的功能,都會(huì)回到之前的頁(yè)面去復(fù)制粘貼,由于處于不同的頁(yè)面,類(lèi)名需要更換,但是換湯不換藥。

久而久之,重復(fù)代碼越來(lái)越多,但凡改動(dòng)一個(gè)小的地方,都需要改動(dòng)很多代碼,顯得極不方便,也不利于大規(guī)模的進(jìn)行工程化開(kāi)發(fā)。雖然市面上也慢慢出現(xiàn)了  Angular、 Avalon 等優(yōu)秀的前端框架,但是考慮到 SEO  和維護(hù)人員并不好招,很多公司還是選擇求穩(wěn),用套頁(yè)面的形式制作網(wǎng)頁(yè),這對(duì)前端的工程化、模塊化是一個(gè)不小的阻礙。

構(gòu)建工具的出現(xiàn)

不過(guò),隨著 Node 被大力推崇,市面上涌現(xiàn)出大量的構(gòu)建工具,如 Npm  Scripts、Grunt、Gulp、FIS、Webpack、Rollup、Parcel等等。構(gòu)建工具解放了我們的雙手,幫我們處理一些重復(fù)的機(jī)械勞動(dòng)。

舉個(gè)簡(jiǎn)單的例子:我們用 ES6 寫(xiě)了一段代碼,需要在瀏覽器執(zhí)行。但是由于瀏覽器廠商對(duì)瀏覽器的更新非常保守,使得很多 ES6  的代碼并不能直接在瀏覽器上運(yùn)行。這個(gè)時(shí)候我們總不能手動(dòng)將 ES6 代碼改成 ES5 的代碼。于是乎就有了下面的轉(zhuǎn)換。

//編譯前 [1,2,3].map(item => console.log(item)) //編譯后 [1, 2, 3].map(function (item) {   return console.log(item); }); //代碼壓縮后 [1,2,3].map(function(a){return console.log(a)});

就是做了上述的操作,才能使得我們?cè)趯?xiě)前端代碼的時(shí)候,使用最新的 ECMAScript  語(yǔ)法,并且盡可能的壓縮代碼的體積,使得瀏覽器加載靜態(tài)腳本時(shí)能更加快速。

傳統(tǒng)的模塊化

隨著 Ajax 的流行,前端工程師能做的事情就不只是“切圖”  這么簡(jiǎn)單,現(xiàn)在前端工程師能做的越來(lái)越多,開(kāi)始出現(xiàn)了明確的分工,并且能夠與服務(wù)端工程師進(jìn)行數(shù)據(jù)聯(lián)調(diào)。這里說(shuō)的傳統(tǒng)模塊化還不是后現(xiàn)代的模塊化,早期的模塊化是不借助任何工具的,純屬由  JavaScript 完成代碼的結(jié)構(gòu)化。在傳統(tǒng)的模塊化中我們主要是將一些能夠復(fù)用的代碼抽成公共方法,以便統(tǒng)一維護(hù)和管理,比如下面代碼。

function show(id) {   document.getElementById(id).setAttribute('style', "display: block") } function hide(id) {   document.getElementById(id).setAttribute('style', "display: none") }

然后,我們將這些工具函數(shù)封裝到一個(gè) JS 腳本文件里,在需要使用它們的地方進(jìn)行引入。

但是,這種做法會(huì)衍生出兩個(gè)很大的問(wèn)題,一個(gè)是全局變量的污染,另一個(gè)是人工維護(hù)模塊之間的依賴(lài)關(guān)系會(huì)造成代碼的混亂。

<script scr="./utils.js"></script>

例如,當(dāng)我們的項(xiàng)目有十幾個(gè)甚至幾十個(gè)人維護(hù)的時(shí)候,難免會(huì)有人在公用組件中添加新的方法,比如 show  這個(gè)方法一旦被覆蓋了,使用它的人會(huì)得到和預(yù)期不同的結(jié)果,這樣就造成的全局變量的污染。另一個(gè)問(wèn)題,因?yàn)檎鎸?shí)項(xiàng)目中的公用腳本之間的依賴(lài)關(guān)系是比較復(fù)雜的,比如 c  腳本依賴(lài) b 腳本,a 腳本依賴(lài) b 腳本,那么我們?cè)谝氲臅r(shí)候就要注意必須要這樣引入。

<script scr="c.js"></script> <script scr="b.js"></script> <script scr="a.js"></script>

要這樣引入才能保證 a 腳本的正常運(yùn)行,否則就會(huì)報(bào)錯(cuò)。對(duì)于這類(lèi)問(wèn)題,我們?cè)撊绾谓鉀Q這樣的問(wèn)題呢?

全局變量的污染

解決這個(gè)問(wèn)題有兩種,先說(shuō)說(shuō)治標(biāo)不治本的方法,我們通過(guò)團(tuán)隊(duì)規(guī)范開(kāi)發(fā)文檔,比如說(shuō)我有個(gè)方法,是在購(gòu)物車(chē)模塊中使用的,可以如下書(shū)寫(xiě)。

var shop.cart.utils = {   show: function(id) {     document.getElementById(id).setAttribute('style', "display: block")   },   hide: function(id) {     document.getElementById(id).setAttribute('style', "display: none")   } }

這樣就能比較有效的避開(kāi)全局變量的污染,把方法寫(xiě)到對(duì)象里,再通過(guò)對(duì)象去調(diào)用。專(zhuān)業(yè)術(shù)語(yǔ)上這叫命名空間的規(guī)范,但是這樣模塊多了變量名會(huì)比較累贅,一寫(xiě)就是一長(zhǎng)串,所以我叫它治標(biāo)不治本。

還有一種比較專(zhuān)業(yè)的方法技術(shù)通過(guò)立即執(zhí)行函數(shù)完成閉包封裝,為了解決封裝內(nèi)變量的問(wèn)題,立即執(zhí)行函數(shù)是個(gè)很好的辦法,這也是早期很多開(kāi)發(fā)正在使用的方式,如下所示。

(function() {     var Cart = Cart || {};    function show (id) {      document.getElementById(id).setAttribute('style', "display: block")    }    function hide (id) {      document.getElementById(id).setAttribute('style', "display: none")    }    Cart.Util = {      show: show,      hide: hide    } })();

上述代碼,通過(guò)一個(gè)立即執(zhí)行函數(shù),給予了模塊的獨(dú)立作用域,同時(shí)通過(guò)全局變量配置了我們的模塊,達(dá)到了模塊化的目的。

當(dāng)前的模塊化方案

先來(lái)說(shuō)說(shuō) CommonJS 規(guī)范,在 Node.JS 發(fā)布之后,CommonJS 模塊化規(guī)范就被用在了項(xiàng)目開(kāi)發(fā)中,它有幾個(gè)概念給大家解釋一下。

  • 每個(gè)文件都是一個(gè)模塊,它都有屬于自己的作用域,內(nèi)部定義的變量、函數(shù)都是私有的,對(duì)外是不可見(jiàn)的;

  • 每個(gè)模塊內(nèi)部的 module 變量代表當(dāng)前模塊,這個(gè)變量是一個(gè)對(duì)象;

  • module 的 exports 屬性是對(duì)外的接口,加載某個(gè)模塊其實(shí)就是在加載模塊的 module.exports 屬性;

  • 使用 require 關(guān)鍵字加載對(duì)應(yīng)的模塊,require 的基本功能就是讀入并執(zhí)行一個(gè) JavaScript 文件,然后返回改模塊的 exports  對(duì)象,如果沒(méi)有的話會(huì)報(bào)錯(cuò)的;

下面來(lái)看一下示例,我們就將上面提到過(guò)的代碼通過(guò) CommonJS 模塊化。

module.exports = {   show: function (id) {     document.getElementById(id).setAttribute('style', "display: block")   },   hide: function (id) {     document.getElementById(id).setAttribute('style', "display: none")   } } // 也可以輸出單個(gè)方法 module.exports.show = function (id) {   document.getElementById(id).setAttribute('style', "display: block") }  // 引入的方式 var utils = require('./utils') // 使用它 utils.show("body")

除了 CommonJS 規(guī)范外,還有幾個(gè)現(xiàn)在只能在老項(xiàng)目里才能看到的模塊化模式,比如以 require.js 為代表的 AMD(Asynchronous  Module Definition) 規(guī)范 和 玉伯團(tuán)隊(duì)寫(xiě)的 sea.js 為代表的 CMD(Common Module Definition) 規(guī)范。

AMD 的特點(diǎn):是一步加載模塊,但是前提是一開(kāi)始就要將所有的依賴(lài)項(xiàng)加載完全。CMD 的特點(diǎn)是:依賴(lài)延遲,在需要的時(shí)候才去加載。

AMD

首先,我們來(lái)看一下如何通過(guò) AMD 規(guī)范的 require.js 書(shū)寫(xiě)上述模塊化代碼。

define(['home'], function(){   function show(id) {     document.getElementById(id).setAttribute('style', "display: block")   }     function hide(id) {     document.getElementById(id).setAttribute('style', "display: none")   }   return {     show: show,     hide: hide   }; });  // 加載模塊 require(['utils'], function (cart){   cart.show('body'); });

require.js 定義了一個(gè)函數(shù) define,它是全局變量,用來(lái)定義模塊,它的語(yǔ)法規(guī)范如下:

define(id, dependencies, factory)

  • id:它是可選參數(shù),用于標(biāo)識(shí)模塊;

  • dependencies:當(dāng)前模塊所依賴(lài)的模塊名稱(chēng)數(shù)組,如上述模塊依賴(lài) home  模塊,這就解決了之前說(shuō)的模塊之間依賴(lài)關(guān)系換亂的問(wèn)題,通過(guò)這個(gè)參數(shù)可以將前置依賴(lài)模塊加載進(jìn)來(lái);

  • factory:模塊初始化要執(zhí)行的函數(shù)或?qū)ο蟆?/p>

require([dependencies], function(){})

然后,在其他文件中使用 require  進(jìn)行引入,第一個(gè)參數(shù)為需要依賴(lài)的模塊數(shù)組,第二個(gè)參數(shù)為一個(gè)回調(diào)函數(shù),當(dāng)前面的依賴(lài)模塊被加載成功之后,回調(diào)函數(shù)會(huì)被執(zhí)行,加載進(jìn)來(lái)的模塊將會(huì)以參數(shù)的形式傳入函數(shù)內(nèi),以便進(jìn)行其他操作。

感謝各位的閱讀,以上就是“軟件架構(gòu)之如何理解前后端分離與前端模塊化”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)軟件架構(gòu)之如何理解前后端分離與前端模塊化這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

網(wǎng)站欄目:軟件架構(gòu)之如何理解前后端分離與前端模塊化
鏈接URL:http://m.rwnh.cn/article44/igjcee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)、網(wǎng)頁(yè)設(shè)計(jì)公司網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈、定制網(wǎng)站App設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化
台安县| 安远县| 林周县| 孙吴县| 邮箱| 句容市| 宁河县| 武乡县| 兴化市| 大丰市| 佳木斯市| 蕉岭县| 奎屯市| 东兴市| 苍山县| 九江县| 丁青县| 承德市| 三都| 泽普县| 六盘水市| 邢台市| 灵丘县| 监利县| 鲜城| 无极县| 明水县| 公主岭市| 达拉特旗| 西城区| 鹤峰县| 洛宁县| 和田市| 保亭| 谷城县| 郁南县| 淮阳县| 应用必备| 上杭县| 景泰县| 七台河市|