2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

移動(dòng)端開發(fā)者眼中的前端開發(fā)流程變遷與前后端分離

 melon1024 2016-08-28


是一篇面向移動(dòng)端開發(fā)者的科普性文章,從前端開發(fā)的最初流程開始,結(jié)合示范代碼,討論開發(fā)流程的演變過(guò)程,希望能覆蓋一部分前端開發(fā)技術(shù)棧,從而對(duì)前端開發(fā)的相關(guān)概念形成初步的認(rèn)識(shí)。


本文會(huì)提供一些示范代碼,然而他們無(wú)法運(yùn)行,也不需要完全看懂,更多的是方便讀者對(duì)相關(guān)概念和方案有更加具體形象的感受和更清晰的理解。


 1   移動(dòng)端與前端的區(qū)別


在開發(fā) App 的過(guò)程中,我們不會(huì)刻意思考開發(fā)流程,因?yàn)橐磺锌瓷先ザ挤浅W匀???梢员镜卮_定的內(nèi)容就直接寫死,否則異步發(fā)起網(wǎng)絡(luò)請(qǐng)求并動(dòng)態(tài)的修改,最后把源代碼編譯成可執(zhí)行的二進(jìn)制文件供客戶安裝。


前端開發(fā)和移動(dòng)端開發(fā)就有本質(zhì)的不同了。一個(gè)網(wǎng)頁(yè)的最終展現(xiàn)樣式受到 HTML CSS 的影響,而 JavaScript 腳本負(fù)責(zé)用戶交互。一個(gè)頁(yè)面不會(huì)被編譯成可執(zhí)行文件,它僅僅由幾個(gè)文本文件組成,由服務(wù)端明文下發(fā)給瀏覽器并繪制到屏幕上。


下文中可能會(huì)反復(fù)提到“渲染”的概念,除非特別說(shuō)明,它不表示解析 HTML 文檔(DOM)并繪制到屏幕上這個(gè)過(guò)程,因?yàn)檫@一步由瀏覽器內(nèi)核實(shí)現(xiàn),普通情況下不需要做過(guò)多了解和干預(yù)。


網(wǎng)頁(yè)可以分為靜態(tài)、動(dòng)態(tài)兩種,前者就是一個(gè) HTML 文件,后者可能只是一份模板,在請(qǐng)求時(shí)動(dòng)態(tài)的計(jì)算出數(shù)據(jù),最后拼接成 HTML 格式的字符串,這個(gè)過(guò)程就被稱為渲染。


前端與移動(dòng)端開發(fā)另一個(gè)顯著差異是: 雖然可以在本地調(diào)試 HTML,但實(shí)際上這些 HTML 的內(nèi)容需要部署在服務(wù)端,這樣才能在用戶發(fā)起 HTTP 請(qǐng)求時(shí)返回 HTML 格式的文本。


 2   前端開發(fā)的混沌時(shí)代


一開始,我們沒(méi)有任何工具,只能靠蠻力。我們知道 Servlet 是由 Java 編寫的服務(wù)端程序,可以方便的處理 HTTP 請(qǐng)求和返回,因此可以直接把 HTML 文本當(dāng)做字符串返回,也就是上文所說(shuō)的渲染:

(上下滑動(dòng)看代碼)

public class HelloWorldServlet extends HttpServlet {

    @Override

    public void doGet(HttpServletRequest req, HttpServletResponse resp)

        throws ServletException, IOException {

        resp.setContentType('text/html');


        PrintWriter out = resp.getWriter();

        out.println('<html><head><title>Hello World Sample</title></head>');

        out.println('<body><h1>Hello World Title<h1><h2>' new Date().toLocaleString() '</h2></body></html>');

        out.flush();

    }

}

理論上來(lái)說(shuō),我們已經(jīng)可以開始所有前端開發(fā)了,但在這混沌初開的年代,想寫出一份可維護(hù)的代碼恐怕得用上“洪荒之力”。把 UI 和業(yè)務(wù)邏輯寫在一起是一種非常強(qiáng)的耦合,不利于項(xiàng)目日后的拓展。也無(wú)法要求每個(gè)人同時(shí)會(huì)寫 Java 和前端。


 3   后端 MVC


上述方案的問(wèn)題之一在于邏輯混亂不清,移動(dòng)開發(fā)者在入門階段大多也經(jīng)歷過(guò),解決方案比較簡(jiǎn)單:使用 MVC,把業(yè)務(wù)邏輯抽離到 Controller 中,讓 View 層專注于顯示 UI。


 4   MVC 方案實(shí)現(xiàn)


在前端開發(fā)領(lǐng)域,也有類似的技術(shù),比如 JSP,它經(jīng)過(guò)編譯后變成 Servlet。在寫 JSP 的時(shí)候,我們更加關(guān)心頁(yè)面樣式,因此代碼看起來(lái)就像是 HTML,不過(guò)在 <% %> 代碼塊中可以調(diào)用 Java 函數(shù):

(上下滑動(dòng)看代碼)

<HTML>

<HEAD>

<TITLE>JSP測(cè)試頁(yè)面---HelloWorld!</TITLE>

</HEAD>

<BODY>

<%

    out.println('<h1>Hello World!</h1>');

%>

</BODY>

</HTML>

JSP 相當(dāng)于 View 層,它從 Model 中獲取數(shù)據(jù),說(shuō)的再具體一點(diǎn),是使用后端的語(yǔ)言(比如 Java)去訪問(wèn) Model 層提供的接口。


Controller 作為直接和客戶端接觸的模塊,負(fù)責(zé)解析請(qǐng)求,數(shù)據(jù)校驗(yàn),路由分發(fā),結(jié)果返回等等邏輯。路由分發(fā)是指根據(jù)請(qǐng)求路徑的不同,調(diào)用不同的 Model 和 View 提供服務(wù)。


 5   MVC的缺點(diǎn)與改進(jìn)


使用了 MVC 架構(gòu)(比如大名鼎鼎的 Struts)后,似乎職責(zé)變清晰了,前端開發(fā)者負(fù)責(zé)寫 JSP,后端開發(fā)者負(fù)責(zé)寫 Controller 和 Model,然而在實(shí)際開發(fā)時(shí)還是有諸多問(wèn)題。


首先業(yè)務(wù)邏輯依然沒(méi)有嚴(yán)格區(qū)分,如果沒(méi)有良好的編碼規(guī)范,JSP 中就會(huì)混入大量業(yè)務(wù)邏輯。而一個(gè)框架存在的作用應(yīng)該是讓沒(méi)有接受很多培訓(xùn)的新人也能寫出合格的代碼。此外,前端開發(fā)者還需要對(duì)后端邏輯有大致的了解,熟悉后端編程語(yǔ)言,因此也存在很多溝通、學(xué)習(xí)成本。


 6   前端只寫Demo


一種解決方案是前端開發(fā)者只寫 Demo,也就是提供靜態(tài)的 HTML 效果給后端開發(fā)者,由后端開發(fā)者去完成視圖層(比如 JSP)的開發(fā)。這樣前端開發(fā)者就完全不需要了解后端知識(shí)了。


可惜這種想法很好,但是一旦付諸實(shí)現(xiàn)就會(huì)遇到不少問(wèn)題。首先后端開發(fā)者依賴于前端的 Demo,只有看到 HTML 文件他們才可以開始實(shí)現(xiàn) View 層。而前端又依賴于后端開發(fā)者完成整體的開發(fā),才能通過(guò)網(wǎng)絡(luò)訪問(wèn)來(lái)檢查最終的效果,否則他們無(wú)法獲取真實(shí)的數(shù)據(jù)。


更糟糕的是,一旦需求發(fā)生變動(dòng),上述流程還需要重新走一遍,前后端的交流依舊無(wú)法避免。概況來(lái)說(shuō)就是前后端對(duì)接成本太高。


舉個(gè)例子,在開發(fā) App 的時(shí)候,你的同事給你發(fā)來(lái)一段代碼,其中是一個(gè)本地寫死的視圖,然后告訴你:“這個(gè)按鈕的文字要從數(shù)據(jù)庫(kù),那個(gè)圖片的內(nèi)容要通過(guò)網(wǎng)絡(luò)請(qǐng)求獲取,你把代碼改造一下吧?!薄S谑悄慊税胩鞎r(shí)間改好了代碼,PM 跑來(lái)告訴你按鈕文字寫死就好,但是背景顏色要從數(shù)據(jù)庫(kù)讀取,另外,再加一個(gè)按鈕吧。WTF?


顯然這種開發(fā)流程效率極低,難以接受。


 7   HTMl模板


其實(shí)一定程度上來(lái)說(shuō),JSP 可以看做 HTML 模板的雛形。HTML 大體上肩負(fù)了兩個(gè)任務(wù): 頁(yè)面框架和內(nèi)容描述。所謂的 HTML 模板是指利用一種結(jié)構(gòu)化的語(yǔ)法,表示出 HTML 的框架,同時(shí)把具體數(shù)據(jù)抽離出來(lái)。


比如 <p>111</p> 表示一個(gè)段落,其中內(nèi)容為 “111”。如果用模板來(lái)表示,可以寫作 <p>Content</p> 或者 p Content 等等。總之,不要糾結(jié)于具體語(yǔ)法,我們只要知道:

數(shù)據(jù) 模板 = HTML 源碼


比如在 Controller 層,可以這樣調(diào)用:

// 這里沒(méi)有指定模板的名稱,是因?yàn)槭褂昧艘蕾嚨怪玫乃枷?,在配置文件中綁定?Controller 對(duì)應(yīng)的 View

return res.view({title: '111'});


模板中的代碼如下:

<h1><%= Content%></h1>


熟悉前端開發(fā)的讀者可能會(huì)發(fā)現(xiàn),這其實(shí)采用了 Sails.js EJS 開發(fā)。前者是基于 JavaScript 的服務(wù)端應(yīng)用程序,后者是基于 HTML 語(yǔ)法的模板,另一種風(fēng)格的模板是 Jade,不過(guò)本文的目的并不是重點(diǎn)介紹這些工具如何使用,就不再贅述了。


回到模板的概念上來(lái),它相對(duì)于 JSP 的優(yōu)勢(shì)在于,利用工具強(qiáng)行禁止前端開發(fā)者在視圖層寫業(yè)務(wù)邏輯。前端開發(fā)者只需要關(guān)心 UI 實(shí)現(xiàn)并確定 HTML 中的變量。而后端開發(fā)者只要傳入?yún)?shù)即可獲取 HTML 格式的字符串。


模板開發(fā)的另一個(gè)好處是前后端可以同步開發(fā)。雙方約定一個(gè)數(shù)據(jù)格式,前端就可以模擬出假數(shù)據(jù)并用來(lái)自測(cè),后端也可以用生成的數(shù)據(jù)與假數(shù)據(jù)對(duì)比進(jìn)行測(cè)試。同時(shí),這個(gè)約定的數(shù)據(jù)格式扮演了契約和文檔的作用,規(guī)范了雙方的數(shù)據(jù)交流形式,從而節(jié)省交流的時(shí)間成本。關(guān)于更多 Mock Server 的話題,請(qǐng)參考 這個(gè)連接。


 8   后端MVC架構(gòu)總結(jié)


使用后端 MVC 架構(gòu)加上模板開發(fā)是當(dāng)前比較主流的一種開發(fā)模型,但它也不是完美的。由于模板由前端開發(fā)者完成,所以要求前端開發(fā)者對(duì)后端環(huán)境(注意這里不是實(shí)現(xiàn)細(xì)節(jié))有所了解。


舉個(gè)簡(jiǎn)單例子,大型應(yīng)用的后端要分很多文件夾,這就要求前端對(duì)代碼組織結(jié)構(gòu)有所了解,上傳文件時(shí)需要掌握 ssh、vim 并且依賴于服務(wù)端環(huán)境。


總的來(lái)說(shuō),采用服務(wù)端 MVC 方案時(shí),HTML 在后端渲染,整體開發(fā)流程也全部基于后端環(huán)境。因此前端工程師不可避免的需要依賴于后端(雖然使用模板后情況已經(jīng)大大改善)。


 9   AJAX與前端MVC


AJAX 的全稱是 Asynchronous Javascript And XML,即 “異步 JavaScript 和 XML”。它并非一個(gè)框架,而是一種編程思想。它利用 JavaScript 異步發(fā)起請(qǐng)求,結(jié)果以 XML 格式返回,隨后 JavaScript 可以根據(jù)返回結(jié)果局部操作 DOM。


AJAX 最大的優(yōu)點(diǎn)是不用重新加載全部數(shù)據(jù),而是只要獲取改動(dòng)的內(nèi)容即可。這在移動(dòng)端編程中看上去是天經(jīng)地義的,而前端開發(fā)則需要專門使用 AJAX 來(lái)實(shí)現(xiàn),默認(rèn)情況下網(wǎng)頁(yè)的任何一處微小改動(dòng)都需要重新加載整個(gè)網(wǎng)頁(yè)。


類比移動(dòng)應(yīng)用就會(huì)發(fā)現(xiàn),AJAX 適合做單頁(yè)面更新,但是不擅長(zhǎng)頁(yè)面跳轉(zhuǎn),就像你的 app 頁(yè)面跳轉(zhuǎn)都是新建一個(gè) UIViewController/Activity 而不是直接把當(dāng)前頁(yè)面的內(nèi)容全部換掉。


得益于 AJAX 的提出,HTML 在前端渲染變成了可能。我們可以下載一個(gè)空殼 HTML 文件和一個(gè) JavaScript 腳本,然后在 JavaScript 腳本中獲取數(shù)據(jù),為 DOM 添加節(jié)點(diǎn)。


這時(shí)候就出現(xiàn)了很多前端的 MVC 框架,比如 Backbone.js,AngularJS(姑且認(rèn)為MVVM 是 MVC 的變種) 等一堆名詞,你可以從 這里 找到他們各自的 Demo。以我相對(duì)熟悉的 React 為例:

(上下滑動(dòng)看代碼)

<!DOCTYPE html>

<html>


<head>

  <script src='../build/react.js'></script>

  <script src='../build/react-dom.js'></script>

  <script src='../build/browser.min.js'></script>

</head>


<body>

  <div id='example'></div>

  <script type='text/babel'>

    var LikeButton = React.createClass({ 

      getInitialState: function() { 

        return {liked: false}; 

      }, 

      handleClick: function(event) { 

        this.setState({liked: !this.state.liked}); 

      }, 

      render: function() { 

        var text = this.state.liked ? 'like' : 'haven\'t liked'; 

        return (

          <p onClick={this.handleClick}>

            You {text} this. Click to toggle.

          </p>

        ); 

      } 

    }); 

    ReactDOM.render(

      <LikeButton />, 

      document.getElementById('example') 

    );

  </script>

</body>


</html>

這段代碼不用完全讀懂,你只要意識(shí)到,引入 React.js 這個(gè)框架后,我們就可以脫離 HTML 編程了。所有的邏輯都寫在 <script> 標(biāo)簽塊中的 JavaScript 代碼中。


我們還創(chuàng)建了一個(gè) LikeButton 組件,它可以擁有自己的方法,管理自己的狀態(tài)等等。這里舉 React 的例子可能略有不妥,因?yàn)樗鋵?shí)只是一個(gè) View 層的實(shí)現(xiàn)方案,還需要配合 Flux 或 Redux 架構(gòu)。不過(guò)也足以感受一下純 JavaScript 開發(fā)的感覺(jué)了。


這種開發(fā)模式和移動(dòng)端開發(fā)非常類似,使用 JavaScript 調(diào)用 DOM 接口來(lái)繪制視圖,使用 JavaScript 來(lái)實(shí)現(xiàn)業(yè)務(wù)邏輯,處理數(shù)據(jù),發(fā)起網(wǎng)絡(luò)請(qǐng)求等。你完全可以理解為單純用 JavaScript 在瀏覽器上開發(fā)移動(dòng)應(yīng)用,只不過(guò)用戶下載的是 JavaScript 腳本而非傳統(tǒng)靜態(tài)語(yǔ)言編譯后的二進(jìn)制文件。


使用了前端 MVC 框架后,對(duì)于單頁(yè)應(yīng)用(Single Page Application)來(lái)說(shuō),前后端各司其職,唯一的聯(lián)系就變成了 API 調(diào)用,前端開發(fā)者不再依賴后端環(huán)境,HTML 和 JavaScript 都可以放在 CDN 服務(wù)器上。這就是我們常說(shuō)的 前后端分離 的基本概念,即前端負(fù)責(zé)展現(xiàn),后端負(fù)責(zé)數(shù)據(jù)輸出。


 10   前后端分離的缺點(diǎn)


然而在我看來(lái),上述前后端分離方案遠(yuǎn)遠(yuǎn)遜色于后端 MVC 模板的開發(fā)流程,這是因?yàn)樵趯?shí)際開發(fā)中,純 SPA 的場(chǎng)景并不多見,即使移動(dòng)端也不是只有一個(gè)視圖,而是有很多頁(yè)面跳轉(zhuǎn)邏輯,更何況到處都是超鏈接的網(wǎng)頁(yè)呢?


我們來(lái)看看在 SPA 和多頁(yè)面跳轉(zhuǎn)并存的情況下,采用前端 MVC 框架進(jìn)行前后端分離存在哪些不足。


 11   雙端MVC不統(tǒng)一


前端的 MVC 主要處理單個(gè)頁(yè)面內(nèi)的邏輯,而后端 MVC 框架處理的是整個(gè) Web 服務(wù)器的邏輯。借用 jsconf 大會(huì) 上 赫門 的圖片來(lái)表示:


前后端 MVC 架構(gòu)示意圖


由于前后端 MVC 框架關(guān)注的重點(diǎn)不同,它們的地位自然也不同。前端的 MVC 框架負(fù)責(zé)頁(yè)面展示,因此它只是后端 MVC 框架的 View 層(或許只是一部分 View)。


這就會(huì)導(dǎo)致如下問(wèn)題:

  1. 前端的 Model 和后端的 Model 結(jié)構(gòu)上高度類似,比如前端用到一個(gè) name 屬性,后端也得在 JavaBean 中定義一個(gè) name。有時(shí)候?yàn)榱吮苊馇岸藢?duì)數(shù)據(jù)做太多邏輯處理從而導(dǎo)致性能下降,后端可能已經(jīng)做了一些預(yù)處理。這就好比我們寫 App 時(shí),拿到的 feed 流可能是篩選、排序過(guò)的,而我們?cè)谝苿?dòng)端還要在 ViewModel 中做一些轉(zhuǎn)化才能給 View 使用。因此,前后端邏輯上的耦合還是無(wú)法完全避免。

  2. 前端的 Controller 負(fù)責(zé)頁(yè)面調(diào)度,比如控件的狀態(tài)管理和樣式改變等。而后端的 Controller 負(fù)責(zé)調(diào)用服務(wù),用戶鑒權(quán)等。兩者完全不等價(jià)。

  3. 前端也有路由模塊,它主要負(fù)責(zé)頁(yè)面內(nèi)控件之間的跳轉(zhuǎn),比如 React-Router,而后端路由則是把不同的網(wǎng)絡(luò)請(qǐng)求分發(fā)給指定的 Controller。兩者邏輯也無(wú)法統(tǒng)一。


 12   SEO


SEO(搜索引擎優(yōu)化)是一個(gè)移動(dòng)開發(fā)者從來(lái)不考慮,但前端開發(fā)者視作生命的問(wèn)題。搜索引擎的工作原理是訪問(wèn)每個(gè)網(wǎng)頁(yè),然后分析 HTML 中的標(biāo)簽和關(guān)鍵字并做記錄。


一個(gè)純異步的網(wǎng)頁(yè),HTML 幾乎是空殼子,而偏偏關(guān)鍵的數(shù)據(jù)都是動(dòng)態(tài)下發(fā)的,這就影響了搜索引擎爬蟲的工作過(guò)程,他們會(huì)認(rèn)為該網(wǎng)頁(yè)什么都沒(méi)有,即使記錄下來(lái)的也是非關(guān)鍵數(shù)據(jù)。


早些年谷歌推出了 Hash-bang 協(xié)議 來(lái)彌補(bǔ) AJAX 對(duì) SEO 造成的負(fù)面影響,它的本質(zhì)是為爬蟲提供后端渲染的降級(jí)處理機(jī)制。目前谷歌的爬蟲一定程度上可以閱讀 JavaScript 代碼并爬取相關(guān)數(shù)據(jù),但 AJAX 在對(duì)爬蟲的支持上終究不如 HTML 文本直接傳輸。


 13   性能不夠


從上文中 React 的示范代碼可以看出,HTML 文件非常小,很快就被打開。但是頁(yè)面的渲染邏輯直到 JavaScript 文件被下載后才能開始執(zhí)行,這就會(huì)導(dǎo)致一段時(shí)間的白屏。


在移動(dòng)網(wǎng)絡(luò)上,前端渲染 HTML 的性能當(dāng)然不如后端渲染,頻繁發(fā)送 HTTP 請(qǐng)求也會(huì)影響加載體驗(yàn),因此依賴于前端渲染的頁(yè)面,在性能方面還有很大的提高空間。


 14   集中 Or 分離


很多年前,JavaScript 和 CSS 并不用單獨(dú)寫在外部文件中,而是直接內(nèi)嵌在 HTML 代碼里:

<p style='background-color:green'

    onclick='javascript:myFunction()'>

    This is a paragraph.

</p>


為了便于管理和修改,我們把 CSS 和 JavaScript 分離出來(lái)。然而到了 React 中,好像走了回頭路,所有邏輯都放在 JavaScript 中。


我的理解是,這種做法適合組件化,我們很容易定義出一個(gè)組件并且重用。這種思想對(duì)于復(fù)雜的 SPA 來(lái)說(shuō)或許適用,但對(duì)于并不復(fù)雜但有多個(gè)頁(yè)面的網(wǎng)頁(yè)來(lái)說(shuō),就顯得太重了。引入了 React 這樣的框架,以及 MVC 的結(jié)構(gòu),反而會(huì)顯得過(guò)度設(shè)計(jì),增加代碼量和復(fù)雜度。


考慮到之前所說(shuō)的前后端邏輯不能復(fù)用的問(wèn)題,這就更容易導(dǎo)致性能問(wèn)題。


 15   Node.js


前后端分離的哲學(xué)

至此,我們已經(jīng)嘗試過(guò)后端 MVC 架構(gòu),HTML 模板,前端 MVC 架構(gòu)等多種方案,但結(jié)果總是難以令人滿意,是時(shí)候總結(jié)原因了。


我們?cè)谶M(jìn)行上述實(shí)踐的過(guò)程中,過(guò)度強(qiáng)調(diào)物理層上的前后端分離,但是忽略了兩者天然就存在一定的耦合。實(shí)際上,前端開發(fā)者不僅關(guān)注 View 的實(shí)現(xiàn),還應(yīng)該負(fù)責(zé)一部分 Controller 中的邏輯,后端開發(fā)者則應(yīng)該關(guān)心數(shù)據(jù)獲取與處理,以及一些跨終端的業(yè)務(wù)邏輯。


如果頁(yè)面渲染在后端實(shí)現(xiàn),會(huì)導(dǎo)致前端開發(fā)者依賴后端實(shí)現(xiàn)和開發(fā)環(huán)境,后端開發(fā)者被迫熟悉前端邏輯(此時(shí)不是調(diào)用 API 而是直接生成數(shù)據(jù)并套用模板,這就要求把獲取的數(shù)據(jù)轉(zhuǎn)換成模板需要的數(shù)據(jù))。


如果頁(yè)面渲染全部放在前端,業(yè)務(wù)邏輯就會(huì)太靠前,從而導(dǎo)致不能復(fù)用。這種做法似乎有些矯枉過(guò)正了。此外,上文中也介紹了不少 AJAX 的缺點(diǎn),就不贅述了。


我們似乎陷入了兩難的境地,頁(yè)面渲染不管是放在前端還是后端都不合適。其實(shí)這很好理解,頁(yè)面渲染涉及數(shù)據(jù)邏輯和 UI,他們理應(yīng)分別由前后端開發(fā)者分別負(fù)責(zé),單獨(dú)交給任何一方都顯得不合適。


但如果前端工程師可以寫后端代碼,問(wèn)題不就迎刃而解了么?實(shí)際上數(shù)據(jù)的處理可以分為兩個(gè)步驟:從數(shù)據(jù)庫(kù)或第三方服務(wù)獲取數(shù)據(jù),把數(shù)據(jù)轉(zhuǎn)化為 View 可用的形式。前者往往和 C /Java 服務(wù)器相關(guān),后者則和前端模板相關(guān),它的作用更像是 MVVM 架構(gòu)中的 ViewModel。


Node.js 分層

我在上一篇文章中初步介紹了 Node.js 的定位:“一個(gè)用 JavaScript 進(jìn)行開發(fā)的后端應(yīng)用程序框架”。因此它恰好可以完美的解決前端不了解后端邏輯和代碼的問(wèn)題。


Node.js 作為一個(gè)中間層,調(diào)用上游 Java 服務(wù)器提供的服務(wù),獲取數(shù)據(jù)。自身負(fù)責(zé)處理業(yè)務(wù)邏輯,路由請(qǐng)求,cookie 讀寫,頁(yè)面渲染等。前端則負(fù)責(zé)應(yīng)用 CSS 樣式和 JavaScript 交互,類似于最早期原始的模型。


借用 玉伯的 Web研發(fā)模式演變 中的圖片來(lái)說(shuō)明:


node.js 中間層


 16   實(shí)戰(zhàn)應(yīng)用


這不是一篇介紹 Node.js 的文章,我也不熟悉相關(guān)框架的應(yīng)用,舉這個(gè)例子是為了演示 Node.js 是如何做前后端分離的。


我選擇了 Sails.js 框架,項(xiàng)目的代碼在 Github: sails-react-example,這里簡(jiǎn)單的分析一下。


視圖都放在 views 目錄下,采用 EJS 為模板,由 Node.js 負(fù)責(zé)在服務(wù)端渲染:

(上下滑動(dòng)看代碼)

<div class='container'>

<h1><%= __('Comment') %>s for SAILS<small>js</small> REACT<small>js</small></h1>

</div>

<script src='/js/commentMain.js'></script>

Controllers 負(fù)責(zé)頁(yè)面轉(zhuǎn)發(fā)與模板渲染,具體的服務(wù)轉(zhuǎn)交給 Services 去完成:


module.exports = {

  app : function(req, res) {

    // 如果有必要,在這里調(diào)用 Services 獲取數(shù)據(jù)

    return res.view({});

  },

};

這個(gè) Demo 中沒(méi)有實(shí)現(xiàn) Services,通常它用于和真正的后端進(jìn)行交互,可以視情況選擇 HTTP 或 SOAP,并對(duì)返回結(jié)果做處理。此外還有 policies/responses 模塊分別對(duì) HTTP 請(qǐng)求和返回內(nèi)容做處理。


前端的相關(guān)代碼都封裝在模板層,能夠與 Node.js 無(wú)縫接合。


 17   風(fēng)險(xiǎn)控制


雖然我們用增加 Node.js 處理層的方式解決了前后端分離中的一些痛點(diǎn),但在實(shí)際應(yīng)用中還是需要考慮得更加周全。


新增一層后,勢(shì)必會(huì)導(dǎo)致性能損耗。然而分層本就是一個(gè)在衡量得失后做出的權(quán)衡,可以通過(guò)各種優(yōu)化把性能損耗降到最低。況且,在 Node.js 這一層還可以使用 BigPipe 來(lái)處理多個(gè)異步請(qǐng)求。


傳統(tǒng)網(wǎng)頁(yè)在加載頁(yè)面時(shí),首先獲取 HTML,然后獲取其中引用的 CSS 和 JavaScript。在服務(wù)端準(zhǔn)備數(shù)據(jù)和網(wǎng)絡(luò)傳輸過(guò)程中,瀏覽器需要一直等待,而 BigPipe 將頁(yè)面分成若干小塊,雖然每個(gè)塊的加載邏輯不變,但塊與塊之間可以形成流水線作業(yè),避免瀏覽器無(wú)意義的等待。


使用 BigPipe 技術(shù)在一定場(chǎng)景下可以代替 Ajax 的多個(gè)異步請(qǐng)求。具體介紹可以參考 BigPipe學(xué)習(xí)研究。


使用 Node.js 后,對(duì)前端開發(fā)者的技術(shù)要求提高了,編碼工作量也會(huì)相應(yīng)的增加。然而這都是工程化的必經(jīng)之路,編碼量增加的背后其實(shí)是溝通、維護(hù)效率的提高。


 18   總結(jié)


為了處理前后端復(fù)雜的邏輯,我們嘗試了使用了后端 MVC 框架來(lái)分離業(yè)務(wù),用 HTML 模板來(lái)分離數(shù)據(jù)和 UI 樣式。使用了 Ajax 技術(shù)的網(wǎng)頁(yè)更適合單頁(yè)應(yīng)用,雖然做到了物理層的分離,但在處理多頁(yè)面時(shí)還是有不少問(wèn)題。


實(shí)際上頁(yè)面渲染本就是前后端共同關(guān)心的話題,我們更應(yīng)該根據(jù)業(yè)務(wù)邏輯進(jìn)行前后端分離。最終選擇了 Node.js,借助它使用 JavaScript 的特性,由前端工程師負(fù)責(zé)獲取數(shù)據(jù)后的處理和模板的使用,分擔(dān)了一部分原本邏輯上屬于前端,但技術(shù)上偏向后端的任務(wù)。這種開發(fā)模式看上去像是一種倒退,其實(shí)是螺旋式的上升與返璞歸真。


Node.js 基于事件和異步 I/O 的特性,以及優(yōu)秀的處理高并發(fā)的能力非常適合前后端分離的場(chǎng)景,使用 BigPipe 等技術(shù)也足以將分層帶來(lái)的損耗降到最低。選擇 Node.js 做前后端分離并不一定最佳實(shí)踐,但在目前看來(lái)有不錯(cuò)的應(yīng)用,同時(shí)也需要一邊探索一邊前進(jìn)。


作者:bestswifter

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多