难点:不同环境下的问题,学习一门语言可能只要几天,但熟悉一门语言的时间可能要1-2年
一、Node与Js的区别
- ECMAScript(语法)
- 定义变量,循环,判断,函数
- 原型链,作用域和闭包,异步
- 不能操DOM,不能监听事件,不能发送ajax
- 不能处理http请求,不能操作文件
- javascript
- 使用ES规范 + web API (DOM,BOM,事件,Ajax)
- Node.js
- 使用ES规范 + Node.js API (http,文件等)
1. 服务稳定性
- server端可能会遭受各种攻击和误操作,接口是暴露在整个互联网
- 单个客户端可以挂,但服务端不能挂
- PM2进程守候(挂了重启)
2. 考虑内存和CPU(优化,扩展)
- 客户端独占一个浏览器,内存和CPU都不是问题,不会造成问题;
- server端要承载很多请求,CPU和内存资源稀缺
- steam写日志,redis存session
3. 日志记录
- 前端只会发起日志,并不关系后续分析 2 服务端需要记录日志,存储日志,分析日志
4. 安全
- 前端攻击 XSS(跨站脚本Cross-site scripting), CSRF(跨站请求伪造Cross-site request forgery)
- 越权操作,数据库攻击等
- 登录验证,预防xss和sql注入
5. 集群和服务拆分
- 产品发展速度快,流量迅速增加
- 扩展机器或者服务拆分来承载大流量
二、搭建
- nodemon 监听文件变化,自动启动node
- cross-env 设置环境变量,兼容mac linux和windows
# package.json
{
"name": "node",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "cross-env NODE_ENV=dev nodemon ./bin/www.js",
"build": "cross-env NODE_ENV=product node ./bin/www.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"cross-env": "^5.2.0",
"mysql": "^2.17.1",
"nodemon": "^1.19.0",
"redis": "^2.8.0"
},
"keywords": [],
"author": "",
"license": "ISC"
}
启动server服务
# bin/www.js
const http = require('http')
const POST = 8000
const serverHandle = require('../index.js')
const server = http.createServer(serverHandle)
server.listen(POST)
console.log(`server linsening at http://127.0.0.1:${POST}`)
封装serverHandle方法
const serverHandle = (req, res) => {
// 记录log
access(`${req.method} -- ${req.url} -- ${req.headers['user-agent']} -- ${Date.now()}`)
// 设置返回的格式为 JSON
res.setHeader('Content-type', 'application/json')
// 获取path
const url = req.url
req.path = url.split('?')[0]
// 解析参数
req.query = querystirng.parse(url.split('?')[1])
// 解析cookie
req.cookie = {}
const cookieStr = req.headers.cookie || '' // key1=val1;key2=val2
cookieStr.split(';').forEach(item => {
if (!item) { return }
const arr = item.split('=')
const key = arr[0].trim()
const val = arr[1].trim()
req.cookie[key] = val
});
// 解析 session (使用 redis)
let needSetCookie = false
let userId = req.cookie.userid
if (!userId) {
needSetCookie = true
userId = `${Date.now()}_${Math.random()}`
// 初始化 redis 中的 session 值
set(userId, {})
}
// 获取 session
req.sessionId = userId
get(req.sessionId).then(sessionData => {
if (sessionData == null) {
// 初始化 redis 中的 session 值
set(req.sessionId, {})
// 设置 session
req.session = {}
} else {
// 设置 session
req.session = sessionData
}
// 处理 post data
return getPostData(req)
}).then(postData => {
req.body = postData
const productResult = handleProductRouter(req, res)
if (productResult) {
// code...
return
}
const userResult = handleUserRouter(req, res)
if (userResult) {
// code...
return
}
// 未命中路由,返回 404
res.writeHead(404, { "Content-type": "text/plain" })
res.write("404 Not Found\n")
res.end()
})
}
module.exports = serverHandle