将本项目clone到本地 git clone https://github.com/yuzd/Spa.git 或者 下载zip到本地javascript
而后用vs 2017或以上版本 打开!css
打开appsettings.json 进行您所使用环境的配置参数:html
参数名称 | 说明 |
---|---|
BackUpLimit | 每一个单页面上传会进行备份,这个参数是应用维度下最多保留几回上传历史 |
BasicAuth | 设置进入系统的帐号密码 |
RedisConnection | 配置redis的链接字符串(为啥用redis请看ssr相关介绍) |
ConnectionString | 配置mysql的链接字符串(为啥用mysql请看ssr相关介绍) |
F5 运行前端
而后打开 http://localhost:5000/adminjava
系统跑起来以后,咱们的前端容器就已经搞定了。node
什么是单页面应用呢?mysql
对于本套系统的规范git
例以下面的例子:github
下面咱们开发一个最简单单页应用web
有2个文件
而后我打包成 detai.zip 文件
进入系统 新建一个单页面应用
接下来我要修改index.html 而后从新部署
从新打包zip 而后
从新访问 http://localhost:5000/detail 进行确认是否修改为功 以下图
你们应该注意到了,前端有改动 只要从新上传马上生效!
若是发布以后发布改错了咋办,固然是马上回滚到上一次的上传版本!
以下图 回滚功能:
从新访问 http://localhost:5000/detail 进行确认是否回滚成功 以下图
我写了一个网页,部署到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的。这点能够你们实验实验!
解决方案: 服务端代码+模板引擎
是用上面的 产品分享页面 为例:
以下图,进入单应用的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脚本一致!
上面的脚本代码咱们用了log组件=》方便的把脚本的执行过程当中记录日志, 固然了 正常业务的服务端渲染逻辑确定不是这么简单的,不用担忧咱们接下来介绍另外2个组件: redis组件 和 db组件
本系统预制了 log组件 redis组件 db组件,若是还有其余须要也能够自行扩展
前面咱们介绍了log组件。 组件的使用采用commmonJS的方式 先 require 进来 才可使用
let log = require('log');
let db = require('db');
let redis = require('redis');
方法 | 参数 | 说明 |
---|---|---|
Info(msg) | string | 记录Info级别日志 |
Warn(msg) | string | 记录Warn级别日志 |
Error(msg) | string | 记录Error级别日志 |
Debug(msg) | string | 记录Debug级别日志 |
日志采用了开源的LogDashbord 中间件解析Nlog的日志文件
前提:如上文中已提到,要在appsettings.json里面配置redisconnection链接字符串
方法 | 参数 | 说明 |
---|---|---|
Get(key) | string | 根据key从redis里面读取信息 |
Set(key,value,senconds) | string,string,int | 根据key把value设置到redis里面,通过senconds(秒)后失效 |
通常作服务端渲染的脚本里面讲究的是执行快,否则服务端代码执行很慢,很严重影响用户体验!
是用上面的 产品分享页面 为例:事先根据productId把product的对象记录在redis里面!
前提:如上文中已提到,要在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”