1. 程式人生 > 實用技巧 >開源netcore前後端分離,前端服務端渲染方案

開源netcore前後端分離,前端服務端渲染方案

SPA單頁面應用容器開源地址:https://github.com/yuzd/Spa

功能介紹

  • 前端應用開發完後打包後自助上傳部署釋出
  • 配合服務端指令碼(javascript)實現服務端業務邏輯編寫渲染SSR功能
  • 可以快速回滾到上一個版本
  • 可以設定環境變數供SSR功能使用
  • 服務端指令碼提供執行日誌 redis db三大元件打造強大的基於js的ssr服務端執行指令碼功能

快速部署(支援docker),各功能介紹使用 請檢視wiki

截圖介紹

首頁

新建單頁面應用

重新部署上傳,回滾上一個上傳版本

全域性配置

服務端SSR指令碼編輯器

日誌檢視

01.快速開始

將本專案clone到本地 git clone https://github.com/yuzd/Spa.git 或者 下載zip到本地

然後用vs 2017或以上版本 開啟!

開啟appsettings.json 進行您所使用環境的配置引數:

引數名稱說明
BackUpLimit 每個單頁面上傳會進行備份,這個引數是應用維度下最多保留幾次上傳歷史
BasicAuth 設定進入系統的賬號密碼
RedisConnection 配置redis的連線字串(為啥用redis請看ssr相關介紹)
ConnectionString 配置mysql的連線字串(為啥用mysql請看ssr相關介紹)

F5 執行

然後開啟 http://localhost:5000/admin

02.單頁面應用規範

系統跑起來之後,我們的前端容器就已經搞定了。

什麼是單頁面應用呢?

  • 就是指一個系統只加載一次資源,之後的操作互動、資料互動是通過路由、ajax來進行,頁面並沒有重新整理。
  • 特點是載入次數少,載入以後效能較高

對於本套系統的規範

  • 不管你用什麼前端技術,只要是 靜態的html,js,css 的前端資源,就可以部署到本系統!
  • 需要有一個約束 需要有index.html

例如下面的例子:

03.單頁面應用部署,回滾

下面我們開發一個最簡單單頁應用

有2個檔案

  • index.html
  • index.js

然後我打包成 detai.zip 檔案

進入系統 新建一個單頁面應用

  • 單頁面名稱我這裡填 detail 釋出成功後可以通過
  • 選擇剛剛的zip 然後點選【建立並部署】
  • 然後開啟 http://localhost:5000/detail 進行確認是否成功 如下圖

接下來我要修改index.html 然後重新部署

重新打包zip 然後

重新訪問 http://localhost:5000/detail 進行確認是否修改成功 如下圖

大家應該注意到了,前端有改動 只要重新上傳立刻生效!

如果釋出之後釋出改錯了咋辦,當然是立刻回滾到上一次的上傳版本!

如下圖 回滾功能:

重新訪問 http://localhost:5000/detail 進行確認是否回滾成功 如下圖

04.單頁面應用做服務端渲染SSR

首先得理解下面兩點

  • 什麼是服務端渲染? 關鍵詞:後端程式碼+模板引擎
  • 什麼場景下需要用到服務端渲染?關鍵詞:seo:動態的標題 Description 等meta資訊

什麼是服務端渲染?下面是我的理解

我寫了一個網頁,部署到web容器後,我開啟瀏覽器請求,服務端收到請求後 先在服務端讀取我的網頁的內容,然後結合 後端程式碼+模板引擎的方式重新渲染再 返回給瀏覽器展示

什麼場景下需要用到服務端渲染?下面是我的理解

當你的頁面的標題,Description 等meta資訊 需要動態指定的時候。 比如:

產品分享頁面

productId=1 productName = "產品A" http://localhost:5000/detai?productId=1

需要Title要指定為 "產品A"

productId=2 productName = "產品B" http://localhost:5000/detai?productId=2

需要Title要指定為 "產品B"

要滿足這個需求 僅僅靠前端是沒有辦法完成的。因為你頁面在頁面ready後再去呼叫ajax方法是沒有辦法動態指定Title的。這點可以大家實驗實驗!

解決方案: 服務端程式碼+模板引擎

本系統最大的亮點來了:模板引擎約定好,前端自己就能搞定服務端js程式碼

是用上面的 產品分享頁面 為例:

如下圖,進入單應用的SSR指令碼編輯功能

預設 指令碼編輯器裡面會 寫好程式碼模板, 如下:

module.exports = {
  main:function (path){
    
  }
};

當提交儲存 指令碼程式碼後,訪問 http://localhost:5000/detai?productId=2 會先把當前頁面的請求url 作為path引數傳到 指令碼的 main 方法!

我們用 log 元件進行打日誌記錄下:

檢視日誌:

業務程式碼 做如下改寫SSR指令碼:

let log = require('log');

module.exports = {
  main:function (path){
    log.Info(path);
    var requestparams = module.exports.GetRequest(path);
    var productTid = requestparams.productId;
    if(!productTid) return;
    if(productTid == 1){
      return {
        ProductName:'產品A'
      };
    }
    else if (productTid == 2){
      return {
        ProductName:'產品B'
      };      
    }
    else {
      return {
        ProductName:'其他產品'
      };      
    }
  },
  /**
   * [獲取URL中的引數名及引數值的集合]
   * 示例URL:http://localhost:5000/detail?productId=2
   * @param {[string]} urlStr [當該引數不為空的時候,則解析該url中的引數集合]
   * @return {[string]}       [引數集合]
  */
  GetRequest:function (urlStr) {
      var url = "?" + urlStr.split("?")[1];
      var theRequest = {};
      if (url.indexOf("?") != -1) {
          var str = url.substr(1);
          strs = str.split("&");
          for (var i = 0; i < strs.length; i++) {
              theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
          }
      }
      return theRequest;
  }
};


注意:上面我把main方法改造了 返回了 一個 物件

{
    "ProductName" : "xxxxxx"
    
}

模板引擎其實很簡單:

SSR指令碼返回了什麼物件 在html中用 @Model.xxxx 的形式使用!!簡單吧!!如下圖:

邏輯和上面的SSR指令碼一致!

如上我們用SSR指令碼程式碼的業務邏輯 + 模板引擎 解決服務端渲染!

上面的指令碼程式碼我們用了log元件=》方便的把指令碼的執行過程中記錄日誌, 當然了 正常業務的服務端渲染邏輯肯定不是這麼簡單的,不用擔心我們接下來介紹另外2個元件: redis元件 和 db元件

05.SSR指令碼的擴充套件元件介紹

本系統預製了 log元件 redis元件 db元件,如果還有其他需要也可以自行擴充套件

前面我們介紹了log元件。 元件的使用採用commmonJS的方式 先 require 進來 才可以使用


let log = require('log');
let db = require('db');
let redis = require('redis');

log元件

方法引數說明
Info(msg) string 記錄Info級別日誌
Warn(msg) string 記錄Warn級別日誌
Error(msg) string 記錄Error級別日誌
Debug(msg) string 記錄Debug級別日誌

日誌採用了開源的LogDashbord 中介軟體解析Nlog的日誌檔案

redis元件

前提:如上文中已提到,要在appsettings.json裡面配置redisconnection連線字串

方法引數說明
Get(key) string 根據key從redis裡面讀取資訊
Set(key,value,senconds) string,string,int 根據key把value設定到redis裡面,經過senconds(秒)後失效

一般做服務端渲染的腳本里面講究的是執行快,不然服務端程式碼執行很慢,很嚴重影響使用者體驗!

是用上面的 產品分享頁面 為例:事先根據productId把product的物件記錄在redis裡面!

db元件

前提:如上文中已提到,要在appsettings.json裡面配置db的連線字串

方法引數說明
Query(sql) string 根據sql從db裡面讀資料,返回db裡row的jsonArry
Query(sql,param) string,object 根據sql從db裡面讀資料,返回db裡row的jsonArry,和上面的區別是可以指定查詢替換符,這樣可以防止sql注入
Excute(sql) string 執行db的 insert,update,delete語句
Excute(sql,param) string,object 執行db的 insert,update,delete語句,和上面的區別是可以指定查詢替換符,這樣可以防止sql注入

是用上面的 產品分享頁面 為例:假如db裡面 有一個product表

指令碼可以這麼寫:

我在實際業務中還這麼用過:

先從redis裡面取,如果redis沒有我就從db裡面取了放進redis!這樣就比較靈活,而且效率也很高!!

全域性配置功能

全域性配置提供一個json編輯器,配置的json資訊,可以直接在html 用 @Model.Env.XXX 的方式使用

例如:我上面配置了一個 test : “111”