原生JavaScript進行前後端同構

wait.發表於2018-12-18

什麼是前後端同構

明確三個概念:「後端渲染」指傳統的 ASP、Java 或 PHP 的渲染機制;「前端渲染」指使用 JS 來渲染頁面大部分內容,代表是現在流行的 SPA 單頁面應用;「同構渲染」指前後端共用 JS,首次渲染時使用 Node.js 來直出 HTML。一般來說同構渲染是介於前後端中的共有部分。

感覺前端的確是折騰,之前還在流行前後端分離,現在怎麼又要做前後端同構了?

原因是現在流行的SPA前端單頁面應用比較沉重,首次訪問需要載入檔案較多,第一次載入過慢,使用者需要等待前端進行渲染頁面。而且不利於SEO及快取,並且有一定的開發門檻。

前後端同構通過複用模板和JS檔案,讓一份程式碼可以同時跑在伺服器和瀏覽器,首次渲染使用nodejs渲染頁面,之後使用SPA路由跳轉。可以有效減少使用者首次訪問的等待時間,並且對SEO比較友好,也便於快取。

專案簡介

本前後端同構專案主要分為兩個部分,一個是基於koa2的渲染伺服器,另一個是基於原生JS和zepto的前端SPA。

專案的特點是不使用vue和react等框架,門檻低,開發速度快,便於上手,比較輕巧,核心的router部分只有一百行左右的程式碼。適用於頁面互動較少,變化不頻繁的場景下,可以有效的提升效能和載入速度。

前端部分

前端部分的核心是路由部分,具體實現可以基於history API或是hash,網上有很多實現,這次主要講下架構 前端部分採用MVC分層結構。

router層做的主要是建立路由示例,呼叫路由的get方法,給特定頁面繫結來自control層的函式。 形式如:

import control from '../control'
 
//路由的建構函式支援傳入渲染函式,路由的全域性名稱,路由跳轉前呼叫的鉤子
router = new Router(render,'ROUTER',beforeFn)
 
router.get('/page/a', control.pageA')
複製程式碼

前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提升思維能力,群內有大量PDF可供自取,更有乾貨實戰專案視訊進群免費領取。

control層主要做的是載入跟後端共有的渲染模板和渲染資料,渲染出頁面後執行頁面函式

形式如:

let control = {
 pageA(req,res) {
  //webpack的動態載入,程式碼分割功能
  import(/* webpackChunkName: "pageA" */'script/pageA').then(module=> {
  // 檢測該頁面是否已有伺服器渲染好,是的話直接執行module.default
  //否則載入模板和資料進行渲染,最後再呼叫頁面函式
  if(this.needRender(module.default)) {
  //載入資料時訪問的地址就是當前準備渲染的頁面地址,只是加上了json=1的引數
   loadData('pageA').then(data => 
    res.render(xtpl,data,module.default))
  }
 }
}
 
// 捕捉webpack熱更新,讓他只進行相當於頁面跳轉的操作而不是重新整理頁面
if(module.hot) {
 module.hot.accept(['script/pageA'], () => {
  control[ROUTER.req.currentControl].call(ROUTER,null,ROUTER.res)
 })
}
複製程式碼

view層即模板,這裡使用的是xtpl模板,在伺服器環境和前端環境下都支援渲染頁面

頁面函式的形式

頁面函式要求使用es6的模組寫法,配合webpack的按需載入功能

export default () => {
 window.addEventListener('scroll', fn)
//頁面函式支援返回一個解除安裝函式,在頁面離開的時候會被呼叫
//主要用於記憶體的釋放,定時器的清除,事件監聽的移除等等
 return function () {
  window.removeEventListener('scroll', fn)
 }
}
複製程式碼

後端部分

使用koa2搭建的一個渲染伺服器,在收到前端傳來的頁面請求時,會向API伺服器請求資料,並識別頁面請求是否帶有json=1的引數,如果帶有,則為前端路由跳轉時的請求,直接返回資料即可,如果沒有帶json引數,載入跟前端共用的模板,配合資料進行渲染,傳送到瀏覽器。

相關文章