这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天
在上这课之前,我有接触过node.js,但更多的是一些小的应用,没有深入去了解过node.js,学了这节课,让我对于node.js的底层有了更深的了解。
Node.js的应用场景
Node.js的应用场景
- 前端工程化
- Web服务端应用
- Electron跨端桌面应用
前端工程化
- Bundle:webpack,vite,esbuild,parcel
- Uglify:uglifyhs
- Transpile:bablejs,typescript
- 其他语言加入竞争:esbuild,parcel,prisma
- 现状:难以替代
Web服务端应用
- 学习曲线平缓,开发效率较高
- 运行效率接近常用的编译语言
- 社区生态丰富及工具链成熟(npm,V8 inspector)
- 与前端结合的场景会有优势(SSR)
- 现状:竞争激烈,Node.js有自己独特的优势
Electron跨端桌面应用
- 商业应用:vscode,slack,discord,zoom
- 大型公司内的效率工具
- 现状:大部分场景在选型时,都值得考虑
Node.js运行时结构
V8:JavaScript Runtime,诊断调试工具(inspector)
libuv:eventloop(事件循环),syscall(系统调用)
特点
- 异步I/O
- 单线程
- 实际:JS线程+uv线程池+V8任务线程池+V8 Inspector线程
- 跨平台(大部分功能,api)
- Node.js跨平台+JS无需编译环境(+Web跨平台+诊断攻击跨平台)
编写Http Server
Http Server + Http Client
Http 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 buf = Buffer.concat(bufs).toString('utf-8')
let msg = 'hello'
try {
const ret = JSON.parse(buf)
msg = ret.msg
} catch (err) {
// res.end('invalid json')
}
const responseJson = {
msg: `receive:${msg}`
}
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify(responseJson))
})
})
server.listen(port, () => {
console.log('listening on ', port)
})
Http Client
const http = require('http')
const body = JSON.stringify({
msg: 'Hello from my own client'
})
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 buf = Buffer.concat(bufs)
const json = JSON.parse(buf)
console.log('json.msg is', json.msg)
})
})
req.end(body)
用Promise+async await重写
const { rejects } = require('assert')
const http = require('http')
const { resolve } = require('path')
const port = 3000
const server = http.createServer(async (req, res) => {
//receive body from client
const msg = await new Promise((resolve, reject) => {
const bufs = []
req.on('data', (buf) => {
bufs.push(buf)
})
req.on('error', (err) => {
reject(err)
})
req.on('end', () => {
const buf = Buffer.concat(bufs).toString('utf-8')
let msg = 'hello'
try {
const ret = JSON.parse(buf)
msg = ret.msg
} catch (err) {
// res.end('invalid json')
}
resolve(msg)
})
})
//response
const responseJson = {
msg: `receive:${msg}`
}
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify(responseJson))
})
server.listen(port, () => {
console.log('listening on ', port)
})
React SSR
const http = require('http')
const React = require('react')
const ReactDOMServer = require('react-dom/server')
function App () {
return React.createElement('h1', {
children: 'Hello',
})
}
const port = 3000
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html')
res.end(
`
<DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<div id="main">
${ReactDOMServer.renderToString(React.createElement(App))}
</div>
</body>
</html>
`
)
})
server.listen(port, () => {
console.log(`server listens on: ${port}`)
})
延伸
Node.js贡献代码
好处
- 从使用者的角色逐步理解底层细节,可以解决更发复杂的问题;
- 自我证明,有助于职业发展;
- 解决社区问题,促进社区发展;
难点
- 花时间
诊断/追踪
- 诊断是一个低频、重要同时也相当有挑战的方向。是企业衡量自己能否依赖一门语言的重要参考。
- 难点
- 需要了解Node.js底层,需要了解操作系统以及各种工具
- 需要经验