array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 开源netcore前后端分离,前端服务端渲染方案 - 爱码网

SPA单页面应用容器 开源地址: https://github.com/yuzd/Spa

功能介绍

  • 前端应用开发完后打包后自助上传部署发布
  • 配合服务端脚本(javascript)实现服务端业务逻辑编写渲染SSR功能
  • 可以快速回滚到上一个版本
  • 可以设置环境变量供SSR功能使用
  • 服务端脚本提供执行日志 redis db三大组件打造强大的基于js的ssr服务端运行脚本功能

快速部署(支持docker),各功能介绍使用 请查看wiki

截图介绍

首页

开源netcore前后端分离,前端服务端渲染方案

新建单页面应用

开源netcore前后端分离,前端服务端渲染方案

开源netcore前后端分离,前端服务端渲染方案

重新部署上传,回滚上一个上传版本

开源netcore前后端分离,前端服务端渲染方案

全局配置

开源netcore前后端分离,前端服务端渲染方案

服务端SSR脚本编辑器

开源netcore前后端分离,前端服务端渲染方案

日志查看

开源netcore前后端分离,前端服务端渲染方案

01.快速开始

开源netcore前后端分离,前端服务端渲染方案

将本项目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 运行

开源netcore前后端分离,前端服务端渲染方案

然后打开 http://localhost:5000/admin

开源netcore前后端分离,前端服务端渲染方案

02.单页面应用规范

系统跑起来之后,我们的前端容器就已经搞定了。

什么是单页面应用呢?

  • 就是指一个系统只加载一次资源,之后的操作交互、数据交互是通过路由、ajax来进行,页面并没有刷新。
  • 特点是加载次数少,加载以后性能较高

对于本套系统的规范

  • 不管你用什么前端技术,只要是 静态的html,js,css 的前端资源,就可以部署到本系统!
  • 需要有一个约束 需要有index.html

例如下面的例子:

开源netcore前后端分离,前端服务端渲染方案

03.单页面应用部署,回滚

下面我们开发一个最简单单页应用

有2个文件

  • index.html
  • index.js

开源netcore前后端分离,前端服务端渲染方案

然后我打包成 detai.zip 文件

进入系统 新建一个单页面应用

开源netcore前后端分离,前端服务端渲染方案

  • 单页面名称我这里填 detail 发布成功后可以通过
  • 选择刚刚的zip 然后点击【创建并部署】
  • 然后打开 http://localhost:5000/detail 进行确认是否成功 如下图

开源netcore前后端分离,前端服务端渲染方案

接下来我要修改index.html 然后重新部署

开源netcore前后端分离,前端服务端渲染方案

重新打包zip 然后

开源netcore前后端分离,前端服务端渲染方案

开源netcore前后端分离,前端服务端渲染方案

重新访问 http://localhost:5000/detail 进行确认是否修改成功 如下图

开源netcore前后端分离,前端服务端渲染方案

大家应该注意到了,前端有改动 只要重新上传立刻生效!

如果发布之后发布改错了咋办,当然是立刻回滚到上一次的上传版本!

如下图 回滚功能:

开源netcore前后端分离,前端服务端渲染方案

重新访问 http://localhost:5000/detail 进行确认是否回滚成功 如下图 开源netcore前后端分离,前端服务端渲染方案

04.单页面应用做服务端渲染SSR

首先得理解下面两点

  • 什么是服务端渲染? 关键词:后端代码+模板引擎
  • 什么场景下需要用到服务端渲染?关键词:seo:动态的标题 Description 等meta信息

什么是服务端渲染?下面是我的理解

我写了一个网页,部署到web容器后,我打开浏览器请求,服务端收到请求后 先在服务端读取我的网页的内容,然后结合 后端代码+模板引擎的方式重新渲染再 返回给浏览器展示

什么场景下需要用到服务端渲染?下面是我的理解

当你的页面的标题,Description 等meta信息 需要动态指定的时候。 比如:

产品分享页面

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

需要Title要指定为 "产品A"

开源netcore前后端分离,前端服务端渲染方案

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

需要Title要指定为 "产品B"

开源netcore前后端分离,前端服务端渲染方案

要满足这个需求 仅仅靠前端是没有办法完成的。因为你页面在页面ready后再去调用ajax方法是没有办法动态指定Title的。这点可以大家实验实验!

解决方案: 服务端代码+模板引擎

本系统最大的亮点来了:模板引擎约定好,前端自己就能搞定服务端js代码

是用上面的 产品分享页面 为例:

如下图,进入单应用的SSR脚本编辑功能

开源netcore前后端分离,前端服务端渲染方案

默认 脚本编辑器里面会 写好代码模板, 如下:

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

当提交保存 脚本代码后,访问 http://localhost:5000/detai?productId=2 会先把当前页面的请求url 作为path参数传到 脚本的 main 方法!

我们用 log 组件进行打日志记录下:

开源netcore前后端分离,前端服务端渲染方案

查看日志:

开源netcore前后端分离,前端服务端渲染方案

业务代码 做如下改写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"
    
}

开源netcore前后端分离,前端服务端渲染方案

模板引擎其实很简单:

SSR脚本返回了什么对象 在html中用 @Model.xxxx 的形式使用!!简单吧!!如下图:

开源netcore前后端分离,前端服务端渲染方案

逻辑和上面的SSR脚本一致!

开源netcore前后端分离,前端服务端渲染方案

如上我们用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的日志文件

开源netcore前后端分离,前端服务端渲染方案

redis组件

前提:如上文中已提到,要在appsettings.json里面配置redisconnection连接字符串

方法 参数 说明
Get(key) string 根据key从redis里面读取信息
Set(key,value,senconds) string,string,int 根据key把value设置到redis里面,经过senconds(秒)后失效

一般做服务端渲染的脚本里面讲究的是执行快,不然服务端代码执行很慢,很严重影响用户体验!

是用上面的 产品分享页面 为例:事先根据productId把product的对象记录在redis里面!

开源netcore前后端分离,前端服务端渲染方案

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表

开源netcore前后端分离,前端服务端渲染方案

脚本可以这么写:

开源netcore前后端分离,前端服务端渲染方案

我在实际业务中还这么用过:

先从redis里面取,如果redis没有我就从db里面取了放进redis!这样就比较灵活,而且效率也很高!!

全局配置功能

全局配置提供一个json编辑器,配置的json信息,可以直接在html 用 @Model.Env.XXX 的方式使用

开源netcore前后端分离,前端服务端渲染方案

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

开源netcore前后端分离,前端服务端渲染方案

开源netcore前后端分离,前端服务端渲染方案

 

 

 

相关文章: