这是我参与「第五届青训营」伴学笔记创作活动的第 11 天
编写Http Server
安装Node.js
- Mac, Linux推荐nvm,多版本管理
- WIndows推荐nvm4w或官方安装包
设置安装源
NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node nvm install 16
编写http server
一个简单的server,返回一个helloworld
const http = require('http')
const port = 3000
const server = http.createServer((req, res) => {
res.end('hello')
})
server.listen(port, () => {
console.log(`server listening on port ${port}`)
})
运行:node http_server.js 取出request内容的一个server
const http = require('http')
const port = 3000
const server = http.createServer((req, res) => {
const bufs = [] //缓冲区
req.on('data', (buf) => {
bufs.push(buf) //读取数据存到缓冲区
})
req.on('end', () => {
const buff = Buffer.concat(bufs).toString('utf-8') //拼接并转换成字符串
try {
const ret = JSON.parse(buff) //JSON解析
const msg = ret.msg || 'Hello'
const responseJSON = {
msg: `reveived: ${msg}`
}
res.setHeader('Content-Type', 'application/json') //添加头
res.end(JSON.stringify(responseJSON)) // 序列化
} catch (error) {
res.end('Invalid JSON !')
}
})
})
server.listen(port, () => {
console.log(`server is listening on port ${port}`)
})
这段代码实现了一个监听在3000端口的服务器,它会读取请求,并将msg(如有)传回,如果没有msg则传回hello。回传的数据格式为JSON
编写http client
const http = require('http')
const msg = JSON.stringify({
msg: 'Test message.',
})
const req = http.request('http://127.0.0.1:3000', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
}, (res) => {
const bufs = []
res.on('data', (buf) => {
bufs.push(buf)
})
res.on('end', () => {
const buff = Buffer.concat(bufs)
const json = JSON.parse(buff)
console.log(`get message: ${json}`)
})
}) //创建请求以及对于响应的回调
req.end(msg)
这段代码的客户端向服务端发送了一个请求,body是一个键值对(msg),受到服务器的响应之后会将其打印在控制台上
通过Promise重构
技巧:callback转换为Promise
function wait(t) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, t)
})
}
上面的代码将定时器写成了promise形式,在结束后调用的事件写在.then里面 promise适合调用一次的函数 改写思路:
- createServer的参数函数写成async
- 在里面,将对于返回数据的处理拆到后面
- 对于请求的处理用await Promise包住,resolve发生在成功读取信息,reject发生在处理异常
编写一个静态文件服务器
const http = require('http')
const fs = require('fs')
const path = require('path')
const url = require('url')
const folderPath = path.resolve(__dirname, './static')
const server = http.createServer((req, res) => {
const info = url.parse(req.url)
const filepath = path.resolve(folderPath, './' + info.path)
const filestream = fs.createReadStream(filepath)
filestream.pipe(res)
})
const port = 3000
server.listen(port, () => {
console.log(`server listening on ${port}`)
})
这个例子中,index.html存放在static文件夹下,用fs和path寻找到文件,使用文件流将HTML文件输出
React SSR
- SSR相比传统HTML模板引擎,避免重复写代码
- 相比SPA(single page application),首屏渲染更快,SEO友好
- 缺点:通常qps较低,前端代码编写时需要考虑服务端渲染情况
需要使用React, ReactDOM 难点:
- 需要处理打包代码
- 需要思考前端代码在服务端运行时的逻辑
- 移除对服务端无意义的副作用或重置环境
调试Debug
围绕V8 Inspector 启用:node --inspect test.js 场景:
- 查看console.log
- breakpoint
- 高CPU、死循环:cpuprofile
- 高内存占用:memory面板
- 性能分析
部署
要解决的问题:
- 守护进程:退出的时候拉起
- 多进程
- 记录状态便于诊断
容器环境:通常有健康检查手段
延伸话题
Node.js贡献代码
- 从使用者角色逐步理解底层细节,解决更复杂的问题
- 助于职业发展
- 解决社区问题,促进社区发展
- 比较花时间
编译Node.js
- 黑盒到白盒
诊断/追踪
- 低频,重要,有挑战
- 技术咨询行业的热门角色
- 需要了解Node.js底层,操作系统及工具
- 需要经验
WASM, NAPI
- Node.js支持WASM
- NAPI执行C接口代码,同时保留原生代码的性能
- 不同编程语言通信的一种方案