Monk.Node 是一个免费开源的,快速、简单的面向对象的轻量级Node.JS开发框架,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。Monk.Node从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。遵循MIT开源许可协议发布,意味着你可以免费使用Monk.Node,甚至允许把你基于Monk.Node开发的应用开源或商业产品发布/销售。
Monk.Node 2.x 版本是一个颠覆和重构版本,采用全新的架构思想,引入了更多的Node.JS新特性,优化了核心,减少了依赖,实现了真正的惰性加载,支持npm,并针对Web开发做了大量的优化,包括路由、日志、异常、模型、数据库、模板引擎和验证等模块都已经重构,但绝对是新项目的首选(无论是WEB还是API开发)。
- 目录规范,代码清晰,极易入门
- 基于 Node.JS 平台构建,Javascript 作为主要开发语言
- 底层以 Express.js 为基石,拓展性强,组件丰富
- 采用主流的 MVC 思想编写,前后端解耦
- 内置 Node.JS 平台下强大的 ORM 组件:Sequelize.js,支持目前主流的数据库操作
- 集成 Web 开发所需的基本组件,无需手工添加
- 支持 WebSocket 开发
- 支持 RESTful API 开发
- 支持 Redis 存储
- 支持 Cors 跨域
- 支持数据库模型自动构建
- 支持有效防止 CSURF 攻击
- 支持邮件发送
- 支持定时任务
- 支持验证码生成
Monk.Node 目前还在持续新增更多新特性,新功能,更多特性可持续关注项目更新。
Monk.Node 基于 Express.js 开发,但更优于 Express.js 本身提供的脚手架!—— 伟大的项目都是站在巨人的肩膀上的 * _* !
- 原创作者:百小僧
- 开源协议:MIT License
- 开发时间:2016年12月06日
- 当前版本:
2.2.9
,2017年02月06日 - 项目名称:Monk.Node
- 开发理念:一切从简,只为了更懒
- 码云地址:http://git.oschina.net/baisoft_org/Monk.Node
- Github :https://github.com/MonkSoul/Monk.Node
-
Monk.Node 静态资源 (项目已调整,请按照最新文档)
-
Monk.Node Redis(未更新)
-
Monk.Node WebSocket(未更新)
-
Monk.Node 入口文件(未更新)
-
Monk.Node RESTful(未更新)
============ 2017.02.06 V2.2.9 ============
- [新增] log4js 日志访问组件
- [新增] config/log4js.json 日志配置文件
- [新增] utils/log4js.js 日志记录工具类
- [修复] 记录日志时,logs文件夹不存在问题
- [更新] README.md 文档
- [更新] package.json依赖模块
============ 2017.01.24 V2.2.8 ============
- [更新] README.md 文档
- [更新] package.json依赖模块
============ 2017.01.12 V2.2.7 ============
- [更新] package.json依赖模块
============ 2016.12.23 V2.2.6 ============
- [更新] app.js 入口文件,将ejs模板引擎文件名改为.html(重点更新)
============ 2016.12.22 V2.2.5 ============
- [新增] locals文件夹,定义全局数据注入,类似ASP.NET MVC的ViewData数据
- [新增] utils/locals.js 模块,全局注入核心模块
- [更新] app.js 核心代码,使其支持全局数据注入
- [更新] utils/route.js 模型,使其支持局部数据注入
- [更新] 使用文档
- [更新] sequelize模块
- [更新] debug模块
- [优化] utils/route.js代码
- [修复] 表单 enctype="multipart/form-data" 数据无法获取问题
============ 2016.12.20 V2.2.3 ============
- [新增] utils/route.js 默认路由区域设置,默认控制器,默认Action路由支持
如:http://localhost:3000 == http://localhost:3000/frontend == http://localhost:3000/frontend/home == http://localhost:3000/frontend/home/index
- [更新] app.js 核心代码
- [更新] multer 文件上传模块
- [更新] debug 调试模块
- [优化] utils/route.js 核心代码
- [删除] app.js 默认首页设置代码,调整为默认区域设置,默认首页由 默认区域,默认控制器,默认Action组成
- [修复] utils/route.js 路由解析 由于node.js版本低导致路由解析报404错误
- [修复] 文档错误问题
============ 2016.12.16 V2.2.1 ============
- [新增] 验证码模块,并编写验证码类库:utils/captcha.js
- [新增] 验证码演示示例,http://localhost:3000/backend/
- [删除] 删除所有区域下的assets资源文件
- [删除] core文件夹,并将db.js,route.js转移到utils目录下
- [更新] 错误提示页面,显示更多错误信息
- [更新] 设置根目录下的public为资源文件,保持和express.js兼容 (重要调整)
- [更新] core/db.js 加载模块代码,新增可配置的加载项
- [更新] 基本示例
- [更新] 静态资源文档
============ 2016.12.15 V2.1.2 ============
- [新增] 数据库操作db全局对象,无需通过 require进来了(**重点更新**)
- [新增] utils/gmodels/js 模块
- [新增] 轻量级的images库,支持图片处理,包括水印,调整大小等等
- [新增] 定时任务node-schedule模块
- [新增] 邮件发送nodemailer模块
- [新增] lodash模块,提供非常方便的JavaScript工具操作库
- [新增] 视频教程
- [优化] 路由核心类库
- [更新] debug模块
- [更新] app.js 错误日志保存方法,以天为单位
- [更新] 默认示例
- [更新] ORM文档
============ 2016.12.14 V2.1.1 ============
- [优化] 全面优化app.js 代码
- [新增] 全局路由过滤器
- [重构] 重构express.js单视图引擎,实现多视图引擎
- [更新] 目录结构,移除根目录下的assets,views文件夹,新增share文件夹
- [更新] postgres 版本
- [更新] socket.io 版本
- [更新] 使用文档
- [修复] Session和Cookie无作用bug
- [修复] core/db.js 加载模型错误
============ 2016.12.13 V2.0.1 ============
- [新增] cors跨域支持
- [新增] 防止csurf攻击支持,提供更安全的开发环境
- [新增] typescript 支持,可以用typescript开发nodejs模块
- [新增] logs/access和logs/error 用于保存日志记录
- [新增] 写入访问日志功能
- [新增] 写入错误日志功能
- [新增] 日志切割功能
- [新增] 支持日志写入文件和写入数据库功能
- [新增] package.json模块依赖 file-stream-rotator
- [优化] app.js 入口文件,提高访问性能
- [更新] 控制台日志输出为combined,之前版本为dev
- [更新] 开发文档,新增防止CSURF攻击示例
============ 2016.12.10 V2.0.0 ============
- [新增] app.js 入口文件默认应用首页设置
- [新增] 支持设置默认控制器,默认Action
- [新增] 区域目录,支持多站点项目开发,默认包含backend(后台),frontend(前台)两个区域
- [新增] core文件夹,将models/index.js模块移动到core/db.js模块
- [调整] public名称为assets,,默认包含backend(后台),frontend(前台),vendor(第三方插件)三个资源目录
- [调整] views视图子目录,默认包含backend(后台),frontend(前台)两个区域视图
- [调整] utils/socketServer.js名称为utils/socket.js
- [优化] app.js 代码,提高加载性能,只支持设置默认区域,默认控制器,默认Action
- [去除] express-controller模块,通过自定义实现更强大的功能
============ 2016.12.08 V1.0.2 ============
- [新增] 即时通讯、聊天示例(推荐)
- [新增] socket.io 支持
- [新增] redis 支持
- [新增] multer 文件上传
- [新增] uploads 文件夹
- [优化] app.js 入口文件 端口和静态文件,用户上传文件代码
- [优化] 代码注释,代码架构
- [修复] package.json 中 mysql依赖包错误
============ 2016.12.07 V1.0.1 ============
- [新增] 演示站点
- [新增] 默认控制器,默认控制器为Home,默认行为为Index
- [新增] model代码生成器
- [新增] package.json 依赖 sequelize-auto
- [优化] 目录解构
- [修复] app.js 入口文件bug
============ 2016.12.06 V1.0.0 ============
- [发布] v1.0.0 版本
初始化目录结构
www WEB部署目录
├─area 区域目录
│ ├─backend 后台区域目录
│ │ ├─controllers 后台控制器目录
│ │ │ ├─homeController.js 后台默认控制器
│ │ ├─views 后台视图目录
│ ├─frontend 前台区域目录
│ │ ├─controllers 前台控制器目录
│ │ │ ├─homeController.js 前台默认控制器
│ │ ├─views 前台视图目录
│ ├─tools 工具区域目录
│ │ ├─controllers 前台控制器目录
│ │ │ ├─generateController.js 数据库模型生成 控制器
│ │ ├─views 后台视图目录
├─config 配置目录
│ ├─db.json 数据库配置文件
├─filters 过滤器,中间件目录
├─locals 全局数据注入目录,支持.json文件和.js模块
├─logs 日志保存目录
│ ├─access 访问日志
│ ├─error 错误日志
├─models 数据库表对应模型目录
├─public 静态资源目录
│ ├─favicon.ico 网站收藏图标
├─uploads 用户上传文件存放目录
├─utils 工具类库目录
│ ├─socket.js Socket.io 服务器演示代码
│ ├─db.js 数据库模型操作核心库
│ ├─route.js 路由解析核心库
├─app.js 入口文件
├─package.json 包配置文件
git
方式
$ git clone https://git.oschina.net/baisoft_org/Monk.Node.git
$ cd Monk.Node
$ npm install
$ npm start
浏览器:http://localhost:3000/
zip
下载
浏览器访问:http://git.oschina.net/baisoft_org/Monk.Node
$ cd Monk.Node
$ npm install
$ npm start
浏览器:http://localhost:3000/
全局数据注入 表示可以在 locals
目录下定义.json
或者.js
模块文件,这个文件中暴露的数据或者接口可以在 整个请求,整个控制器,整个Action和整个视图模板(ejs)中使用
例如:在locals文件夹下定义 setting.js
模块文件
module.exports = {
"name": "Monk.Node",
"version": "2.2.5",
"author": "百小僧",
"company": "百签软件(中山)有限公司"
};
- 在控制器中的使用:res.locals.文件名
module.exports={
get_index:function(req,res){
var setting=res.locals.setting; // setting就是文件名
var name= setting.name; // => Monk.Node
var version= setting.version; // => 2.2.5
}
};
- 在视图页面ejs中使用 _locals.文件名
<%=_locals.setting.name %>
<%=_locals.setting.version %>
<%=_locals.setting.company %>
当然,我们也可以定义局部数据注入,局部数据注入通常在action
中定义的
module.exports={
get_index:function(req,res){
res.locals.abc="我是局部的。。。。。";
}
};
- 在视图页面ejs中使用
<%=_locals.abc %>
全局数据注入使用非常灵活,可以结合数据库操作,最终通过 module.exports
返回json对象
数据即可
- 设置视图模板引擎
app.set('view engine', 'ejs');
- 设置静态资源目录
app.use(express.static(path.join(__dirname, 'public')));
- 设置Cookie,Session配置信息
// cookie处理
app.use(cookieParser());
// session处理
app.use(session({
secret: 'monknode',
cookie: { maxAge: 60000 },
resave: true,
saveUninitialized: true
}));
- 设置默认区域,控制器,Action目录及路由
// 设置控制器文件夹并绑定到路由
resolve
.setRouteDirectory({
areaDirectory: __dirname + '/areas',
controllerDirname: 'controllers',
defautController: 'home',
defautAction: 'index'
})
.bind(router);
- 设置404,500错误处理
// 错误处理
// 404处理
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// 错误或者服务器500异常处理
app.use(function (err, req, res, next) {
var error = (req.app.get('env') === 'development') ? err : {};
//写错误日志
var errorMes = '[' + Date() + ']' + req.url + '\n' + '[' + error.stack + ']' + '\n';
errorLogStream.write(errorMes);
var status = err.status || 500;
res.status(status);
res.send('<pre>' + status + ' ' + err.message + '\n' + errorMes + '</pre>');
});
- 设置网站监听端口,默认是
3000
app.set('port', process.env.PORT || 3000);
- 设置WebSocket启动,并设置服务端处理逻辑
require(path.join(__dirname, 'utils', 'socket')).listen(server);
区域是对网站和代码进行高度组装,如前台,后台。目前区域只支持控制器逻辑的编写。
- 新增区域
只需要在 areas
目录下创建一个文件夹即可,并在此文件夹下创建controllers
目录。如:areas/api/controllers
默认已经包含backend
(后台),frontend
(前台)两个区域
- 访问区域,默认访问的是
homeController
控制器中的get_index
Action。
http://localhost:3000/backend/
http://localhost:3000/frontend/
http://localhost:3000/api/
控制器是整个框架能够在浏览器上正确访问的基础单元,可以说是灵魂。注:控制器中命名为
homeController
的控制器为默认控制器,该控制器中的get_index
为默认Action,此控制器有且只能包含一个Action,也就是get_index
- 创建控制器,控制器文件命名必须以
Controller
结尾,如在frontend
区域中添加controllers/aboutController.js
module.exports={
};
- 在控制器中创建Action,也就是路由,路由遵循
method_action
格式。在aboutController.js
中定义
module.exports={
// 访问地址:http://localhost:3000/frontend/about/
get_index:function(req,res){
res.send("ok");
},
// 提交地址:http://localhost:3000/frontend/about/create
post_create:function(req,res){
res.send("ok");
},
// 访问地址:http://localhost:3000/frontend/about/company/baisoft
get_company_baisoft:function(req,res){
res.send("ok");
},
// 访问地址:http://localhost:3000/frontend/about/company/10
get_company_id:function(req,res,id){
res.send("ok")
},
// 访问地址:http://localhost:3000/frontend/about/company/10/百小僧
get_company_id_name:function(req,res,id,name){
res.send("ok");
},
// 访问地址:http://localhost:3000/frontend/about/百小僧/company
get_name_company:function(req,res,name){
res.send("ok");
},
// 过滤器
get_admin:[function(req,res,next){
if(未登录){
res.redirect("登录页面");
}
else{
next();
}
},function(req,res){
res.send("ok");
}],
// 多个过滤器
get_admin:[function(req,res,next){
console.log("日志记录");
next();
},function(req,res,next){
if(未登录){
res.redirect("登录页面");
}
else{
next();
}
},function(req,res){
res.send("ok");
}],
};
视图模板引擎采用的是
ejs
模板引擎,默认视图目录为:区域下的views
文件夹。ejs详细文档
- 基础语法
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>
- 在控制器中使用
module.exports={
get_index:function(req,res){
res.render("frontend/about/index");
},
get_about:function(req,res){
res.render("frontend/about/index",{
user:{
name:"百小僧"
}
});
}
};
- 引入公共布局
<%- include("header") %>
<%- include("footer") %>
// 传递参数
<%- include("header",{
name:"百小僧"
}) %>
<%- include("footer",{
name:"百小僧"
}) %>
静态资源默认目录为根目录下的
public
目录
- 基础使用
<img src="/imgs/logo.png" />
<link res="stylesheet" href="/css/style.css" />
<script type="text/javascript" src="/js/script.js"></script>
模型主要放在
models
文件夹
- 定义一个和数据库表对应的模型:
member.js
module.exports = function(sequelize, DataTypes) {
return sequelize.define('member', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
name: {
type: DataTypes.STRING,
allowNull: false
}
}, {
tableName: 'member',
timestamps: false,
freezeTableName: true
});
};
由于构建模型是非常耗时而且重复代码多,所以本框架提供了数据表模型生成工具,通过下面地址可以快速构建模型,无需手工操作
生成前需配置 config/db.json
配置文件,通常只需配置数据库类型,数据库连接信息即可
http://localhost:3000/tools/generate/models
数据库操作集成强大的ORM框架:Sequelize.js,支持目前所有主流数据库,详细文档
- 数据库配置信息,配置文件在
config/db.json
下面
{
// 开发环境
"development": {
"username": "sa", // 数据库用户名
"password": "000000", // 数据库密码
"database": "monk_node", // 数据库名称
"host": "MONKSOUL", // 服务器主机地址
"dialect": "mssql", // 数据库类型('mysql'|'mariadb'|'sqlite'|'postgres'|'mssql')
"output": "../models", // 生成实体模型(models)存放的目录
"additional": { // 其他参数
"timestamps": false,
"freezeTableName": true
}
},
// 测试环境
"test": {
"username": "sa",
"password": "000000",
"database": "monk_node",
"host": "MONKSOUL",
"dialect": "mssql",
"output": "../models",
"additional": {
"timestamps": false,
"freezeTableName": true
}
},
// 生产环境
"production": {
"username": "sa",
"password": "000000",
"database": "monk_node",
"host": "MONKSOUL",
"dialect": "mssql",
"output": "../models",
"additional": {
"timestamps": false,
"freezeTableName": true
}
}
}
- CURD
module.exports={
// 新增
post_create:function(req,res){
db.member.create({name:"百小僧"}).then(function(msg){
// 新增成功
console.log(msg);
});
},
// 删除操作
post_delete:function(req,res){
db.member.destroy().then(function(msg){
// 删除成功
console.log(msg);
});
},
// 根据条件删除
post_delete:function(req,res){
db.member.destroy({
where:{
id:10
}
}).then(function(msg){
// 删除成功
console.log(msg);
});
},
// 更新操作
post_delete:function(req,res){
db.member.update({name:'新生帝'},{
where:{
id:10
}
}).then(function(msg){
// 更新成功
console.log(msg);
});
},
// 根据主键查询一条
get_id:function(req,res){
db.member.findById(10).then(function(data){
// 查询成功
console.log(data);
});
},
// 根据条件查询一条
get_one:function(req,res){
db.member.findOne({
where:{
name:"百小僧"
}
}}).then(function(data){
// 查询成功
console.log(data);
});
},
// 查询所有
get_all:function(req,res){
db.member.findAll().then(function(data){
// 查询成功
console.log(data);
});
},
// 根据条件查询
get_all:function(req,res){
db.member.findAll({
where:{
id:{
$gt:2
}
}
}).then(function(data){
// 查询成功
console.log(data);
});
},
// 分页查询
get_all:function(req,res){
db.member.findAll({
offset: 10,
limit: 2,
where:{
isDel:false
}
}).then(function(data){
// 查询成功
console.log(data);
});
}
};
Session、Cookies主要用户存储客户端会话信息,通常用于登录判断
- Session 使用
module.exports={
get_index:function(req,res){
// 检查 session 中的 isVisit 字段
// 如果存在则增加一次,否则为 session 设置 isVisit 字段,并初始化为 1。
if(req.session.isVisit) {
req.session.isVisit++;
res.send('<p>第 ' + req.session.isVisit + '次来此页面</p>');
} else {
req.session.isVisit = 1;
res.send("欢迎第一次来这里");
console.log(req.session);
}
}
}
- Cookies 使用
module.exports={
get_index:function(req,res){
// 如果请求中的 cookie 存在 isVisit, 则输出 cookie
// 否则,设置 cookie 字段 isVisit, 并设置过期时间为1分钟
if (req.cookies.isVisit) {
console.log(req.cookies);
res.send("再次欢迎访问");
} else {
res.cookie('isVisit', 1, {maxAge: 60 * 1000});
res.send("欢迎第一次访问");
}
}
}
过滤器,中间件主要对请求进行过滤的
- 在控制器中直接使用
module.exports={
get_admin:[function(req,res,next){
if(未登录){
res.redirect("登录页面");
}
else{
next();
}
},function(req,res){
res.send("ok");
}]
};
- 全局过滤器,将过滤器定义到
filters
文件夹下,如创建一个loginFilter.js
module.exports = function (req, res, next) {
if(未登录){
res.redirect("登录页面");
}
else{
next();
}
};
在控制器中使用
var loginFilter = require("../../../filters/loginFilter");
module.exports={
get_admin:[loginFilter,function(req,res){
res.send("ok");
}]
}
- 多个过滤器
module.exports={
get_admin:[function(req,res,next){
console.log("日志记录");
next();
},function(req,res,next){
if(未登录){
res.redirect("登录页面");
}
else{
next();
}
},function(req,res){
res.send("ok");
}]
};
- 视图布局:
<h3>表单(不带文件上传,不带: enctype="multipart/form-data"):</h3>
<form action="/backend/home/form1" method="post">
<input type="text" name="name" />
<input type="submit" value="提交">
</form>
<h3>表单(不带文件上传,带: enctype="multipart/form-data"):</h3>
<form action="/backend/home/form2" method="post" enctype="multipart/form-data">
<input type="text" name="name" />
<input type="submit" value="提交">
</form>
<h3>表单(带单个文件上传,带: enctype="multipart/form-data"):</h3>
<form action="/backend/home/form3" method="post" enctype="multipart/form-data">
<input type="file" name="file1">
<input type="text" name="name" />
<input type="submit" value="提交">
</form>
<h3>表单(带多个文件上传,带: enctype="multipart/form-data"):</h3>
<form action="/backend/home/form4" method="post" enctype="multipart/form-data">
<input type="file" name="file1">
<input type="file" name="file1">
<input type="text" name="name" />
<input type="submit" value="提交">
</form>
<h3>表单(带多个文件上传,上传表单名称 不一样(file1,file2,...),带: enctype="multipart/form-data"):</h3>
<form action="/backend/home/form5" method="post" enctype="multipart/form-data">
<input type="file" name="file1">
<input type="file" name="file2">
<input type="text" name="name" />
<input type="submit" value="提交">
</form>
- 控制器Action处理:
var multer = require('multer');
module.exports = {
// 表单(不带文件上传,不带: enctype="multipart/form-data")
post_form1: function (req, res) {
res.json(req.body);
},
// 表单(不带文件上传,带: enctype="multipart/form-data"):
post_form2: [multer().array(), function (req, res) {
res.json(req.body);
}],
// 表单(带单个文件上传,带: enctype="multipart/form-data"):
post_form3: [multer().single('file1'), function (req, res) {
res.send("文件:" + JSON.stringify(req.file) + "<br />表单" + JSON.stringify(req.body))
}],
// 表单(带多个文件上传,带: enctype="multipart/form-data"):
post_form4: [multer().array('file1'), function (req, res) {
res.send("文件:" + JSON.stringify(req.files) + "<br />表单" + JSON.stringify(req.body))
}],
// 表单(带多个文件上传,上传表单名称 不一样(file1,file2,...),带: enctype="multipart/form-data"):
post_form5: [multer().fields([{ name: "file1" }, { name: "file2" }]), function (req, res) {
res.send("文件:" + JSON.stringify(req.files) + "<br />表单" + JSON.stringify(req.body))
}]
};
详细文档,请参考:multer 文档
文件上传集成强大的
multer
组件,详细文档
- 客户端
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="logo">
<input type="submit" value="提交">
</form>
- 服务端
var path = require('path');
var fs = require('fs');
var multer = require('multer');
var upload = multer({ dest: 'uploads/' });
module.exports = {
post_upload: [upload.single('logo'), function(req, res, next) {
var file = req.file;
var ext = path.extname(file.originalname);
fs.rename(file.path, file.path + ext, function(err) {
if (err) {
res.send(JSON.stringify(err));
}
next();
});
}, function(req, res) {
res.send("上传成功");
}]
}
集成了
redis
模块,文档地址
- 基础使用
var redis = require("redis"),
client = redis.createClient();
// if you'd like to select database 3, instead of 0 (default), call
// client.select(3, function() { /* ... */ });
client.on("error", function (err) {
console.log("Error " + err);
});
client.set("string key", "string val", redis.print);
client.hset("hash key", "hashtest 1", "some value", redis.print);
client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
client.hkeys("hash key", function (err, replies) {
console.log(replies.length + " replies:");
replies.forEach(function (reply, i) {
console.log(" " + i + ": " + reply);
});
client.quit();
});
框架已经集成了socket.io ,可以开发实时通信,聊天等应用,详细文档
- 服务端代码,
utils/socket.js
var io = require('socket.io')();
// socket.io 基础使用,监听连接请求
io.on('connection', function (socket) {
console.log("客户端连接成功~~");
// 监听来自客户端事件
socket.on('send', function (data) {
// 调用客户端receive事件,并传递data
io.emit('receive', data);
});
// 这里就写各种监听事件就可以了,
// 通过 socket.on("") 监听客户端事件,通过 io.emit("") 触发所有客户端事件,socket.emit("") 触发指定客户端
});
exports.listen = function (server) {
return io.listen(server);
};
- 客户端代码
<!-- 引入客户端脚本 -->
<script src="/vendors/socket.io/socket.io.js"></script>
<script>
// 连接服务器
var socket = io.connect('http://localhost:3000/');
window.onload=function(){
var send=document.getElementById("send");
send.onclick=function(){
var name=document.getElementById("name").value;
var msg=document.getElementById("msg").value;
// 发送消息
socket.emit('send', { data:name+":"+msg });
};
// 监听服务器消息
socket.on('receive', function (data) {
console.log(data);
var list = document.getElementById("list");
// 写入聊天列表
list.innerHTML=list.innerHTML+"<br />"+data.data;
// 清空msg
document.getElementById("msg").value="";
});
};
</script>
- 服务端
var csrf = require('csurf');
var csrfProtection = csrf({ cookie: true });
module.exports={
post_login:[csrfProtection,function(req,res){
res.send("ok",{ csrfToken: req.csrfToken() });
}]
};
- 客户端
<form action="/process" method="POST">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
Favorite color: <input type="text" name="favoriteColor">
<button type="submit">Submit</button>
</form>
- 安装pm2
$ npm install pm2 -g |
$ pm2 start app.js
- 设置随机启动
$ npm install pm2-windows-startup -g
$ pm2-startup install
$ pm2 save
如果你觉得 Monk.Node 对你有价值,并且愿意让她继续成长下去,你可以资助这个项目的开发,为作者加油打气。
如果你喜欢Monk.Node,可以点击右上角的 star
,想实时关注进度,可以点击右上角的 watch
。
最后,感谢每一个提建议和使用或者捐赠的朋友!因为你们,我们才能坚持!也是因为你们,未来才会更美好!