基于Node.js的Web开发
Web
const http = require('http');
const server = http.createServer((req, res) => {
res.end('Hello World');
});
server.listen(3000);
Koa
const Koa = require('koa');
const app = new Koa();
// response
app.use(ctx => {
ctx.body = 'Hello Koa';
});
app.listen(3000);
module.exports = class Application extends Emitter {
...
listen() {
debug('listen');
const server = http.createServer(this.callback());
return server.listen.apply(server, arguments);
}
use(fn) {
this.middleware.push(fn);
return this;
}
callback() {
const fn = compose(this.middleware);
if (!this.listeners('error').length) this.on('error', this.onerror);
const handleRequest = (req, res) => {
res.statusCode = 404;
const ctx = this.createContext(req, res);
const onerror = err => ctx.onerror(err);
const handleResponse = () => respond(ctx);
onFinished(res, onerror);
return fn(ctx).then(handleResponse).catch(onerror);
};
return handleRequest;
}
createContext(req, res) {
const context = Object.create(this.context);
const request = context.request = Object.create(this.request);
const response = context.response = Object.create(this.response);
context.app = request.app = response.app = this;
context.req = request.req = response.req = req;
context.res = request.res = response.res = res;
request.ctx = response.ctx = context;
request.response = response;
response.request = request;
context.originalUrl = request.originalUrl = req.url;
context.cookies = new Cookies(req, res, {
keys: this.keys,
secure: request.secure
});
request.ip = request.ips[0] || req.socket.remoteAddress || '';
context.accept = request.accept = accepts(req);
context.state = {};
return context;
}
}
Koa 无规范约束,不利于团队开发 ; 中间件繁多,质量参差不齐,选择困难
Think.js 类似.net API
├─src
│ ├─bootstrap
│ ├─config
│ │ ├─config.js
│ │ └─adapter.js
│ ├─controller
│ │ ├─index.js
│ ├─logic
│ │ ├─index.js
│ └─model
├─view
│ ├─index_index.html
└─www
│ └─static
│ ├─css
│ ├─img
│ └─js
├─development.js
├─production.js
├─package.json
// src/controller/index.js
export default class extends think.Controller {
indexAction() {
return this.display();
}
}
// view/index_index.html
<h3>Hello World</h3>
安装 创建项目
$ thinkjs new todo
$ cd todo
$ npm install
simple-todo npm start
> simple-todo@1.0.0 start /Users/lizheming/Desktop/star-plan/simple-todo
> node development.js
API开发 Restful 风格
RESTful 接口规范
每个 API 都对应一种资源或资源集合
使用 HTTP Method 来表示对资源的动作
使用 HTTP Status Code 来表示资源操作结果
创建 API 文件
➜ simple-todo thinkjs controller -r ticket
think-cli · Create: src/controller/rest.js
think-cli · Create: src/controller/ticket.js
think-cli · Create: src/logic/api/ticket.js
配置路由 src/config/router.js
基类自动生成 src/controller/rest.js
getAction
// src/controller/rest.js
async getAction() {
let data;
if (this.id) {
const pk = this.modelInstance.pk;
data = await this.modelInstance.where({ [pk]: this.id }).find();
return this.success(data);
}
data = await this.modelInstance.select();
return this.success(data);
}
其他方法类似
数据库配置
// src/config/adapter.js
exports.model = {
type: 'mysql',
common: {
logConnect: isDev,
logSql: isDev,
logger: msg => think.logger.info(msg)
},
mysql: {
handle: mysql,
database: 'todo',
prefix: '',
encoding: 'utf8',
host: '127.0.0.1',
port: '',
user: 'root',
password: 'root',
dateStrings: true
}
};
http://127.0.0.1:8360/ticket
{
"errno": 0,
"errmsg": "",
"data": [{
"id": 1,
"desc": "八点打扫房间",
"status": 0,
"createdAt": "2018-07-08 17:12:59",
"updatedAt": "2018-07-08 17:13:14"
}]
}
数据校验
// src/logic/ticket.js
module.exports = class extends think.Logic {
getAction() {
this.rules = {
id: {
int: true
}
};
}
deleteAction() {
this.rules = {
id: {
int: true,
required: true,
method: 'get'
}
};
}
putAction() {
this.rules = {
id: {
int: true,
required: true,
method: 'get'
},
status: {
int: true,
required: true
},
desc: {
required: true
}
};
}
postAction() {
this.rules = {
desc: {
required: true
}
};
}
};
DELETE http://127.0.0.1:8360/ticket
{
"errno": 1001,
"errmsg": {
"id": "id can not be blank"
}
}
数据库操作
操作模型
src/model
const model = this.model(modeName);
根据模型名查找 src/model 下的模型文件
文件存在,实例化对应的模型类
文件不存在,实例化 think.Model 类
定义
// src/model/todo.js
module.exports = class TodoModel extends think.Model {
getList () {
// get list
}
}
Node.js调试
日志调试
断点调试
node --inspect
vscode
ndb
NodeJS 6.3+ 使用 node --inspect 参数启动可以在 Chrome 浏览器中调试,在 chrome://inspect 中可以发现你的项目并启动 devtool
Node 开发角色转换
前端
- 跟浏览器打交道,兼容性问题
- 组件化
- 加载速度、JS 执行性能、渲染性能
- 错误监控
- XSS、CSRF 等安全漏洞
服务端
- 数据库、Redis 等周边服务
- 性能、内存泄露、CPU、机器管理
- 服务监控、错误监控、流量监控、报警
- SQL注入、目录遍历等安全漏洞