Node.js学习 | 青训营笔记
这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
今天学习了node.js的部分知识,在此记录一下
介绍:
- node.js的应用场景
- node.js运行时结构
- 编写HTTP server
01:node.js的应用场景
- 前端工程化(例如打包工具,Babel,esbuild等)
- web服务器应用
- Electron跨端桌面应用
前端工程化
- Bundle(打包工具):webpack, vite, esbuild, parcel
- Uglify(代码压缩工具):uglifyjs
- Transpile(语法转换工具):bablejs,typescript
- 其他语言加入:esbuild(go),parcel(rust),prisma
web服务器应用
- 学习曲线平缓,开发效率高
- 运行效率接近常见的编译语言
- 社区生态丰富,工具链成熟(npm,v8 inspector)
- 与前端结合的场景会有优势(ssr服务端渲染)
Electron跨端桌面应用(window,linux,mac端)
- 商业应用:vscode,slack,discord,zoom
- 大型公司内的效率工具
- 现状:大部分场景在选型时,值得考虑
node.js在字节
- BFF应用、SSR应用,例如:Modern.js
- 服务端应用:头条搜索,西瓜视频,懂车帝
- electron:飞书,飞连
02:Node.js运行结构
Node.js运行时结构-V8,libuv
- V8: JavaScript Runtime,诊断调试工具(inspector)
- libuv: eventloop (事件循环,封装各种操作系统api,跨平台io操作),syscall (系统调用)
- 举例:用node-fetch发起请求时
特点
- 异步I/O
- 单线程
- 跨平台
异步I/O
当Node.js执行l/Q操作时,会在响应返回后恢复操作,而不是阻塞线程并占用额外内存等待
单线程
- JS单线程
●实际:JS线程+uv线程池+V8任务线程池+V8Inspector线程
- 优点:不用考虑多线程状态同步问题,也就不需要锁;同时还能比较高效地利用系统资源;
-
缺点:阻塞会产生更多负面影响
●解决办法:多进程或多线程
跨平台
-
跨平台(大部分功能、api)
-
Node.js跨平台+ JS无需编译环境(+ Web跨平台+诊断工具跨平台)
=开发成本低(大部分场景无需担心跨平台问题),整体学习成本低
03:编写Http Server
本节目标
- 安装Node.js
- 编写Http Server + Client, 收发GET, POST请求
- 编写静态文件服务器
- 编写React SSR服务
- 适用inspector进行调试、诊断
- 部署简介
安装Node.js
- Mac, Linux推荐使用nvm。多版本管理。
- Windows推荐nvm4w或是官方安装包。
- 安装慢,安装失败的情况,设置安装源
- NVM_NODEJS_ORG_MIRROR=nommirror.com/mirrors/nod… nvm install 16
编写Http Server + Client, 收发GET, POST请求
promise + await async实现
const http = require('http')
const server = http.createServer(async (req,res)=>{
//receive body through promise
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('utf8')
let msg = 'hello'
try {
const ret = JSON.parse(buf)
msg = ret.msg
} catch (error) {
//
}
resolve(msg)
})
})
//RESPINSE
const responseJson = {
msg:`receive:${msg}`
}
console.log(JSON.stringify(responseJson))
res.setHeader('Content-Type','application/json')
res.end(JSON.stringify(responseJson))
})
const port = 3000
server.listen(port,()=>{
console.log("serve start")
})
http_client.js
const http = require('http')
const body = JSON.stringify({
msg: 'hello from my client'
})
const req = http.request('http://127.0.0.1:3000',{
method:'POST',
headers:{
'Content-Type':'application/json',
},
},(res)=>{
const bufs=[]
res.on('data',data=>{
bufs.push(data)
})
res.on('end',()=>{
const receive = JSON.parse(Buffer.concat(bufs))
console.log('json.msg is:',receive.msg)
})
})
req.end(body)
编写静态文件服务器
与高性能、可靠的服务相比,还差什么? 外部服务: cloudflare, 七牛云,阿里云,火山云.
- 1.CDN:缓存+加速
- 2.分布式储存,容灾
课程代码
//编写静态文件服务
const http = require('http')
const fs = require('fs')
const path = require('path')
const url = require('url')
const port=3000
const folderPath = path.resolve(__dirname,'./static')
const server = http.createServer((req,res)=>{
const info = url.parse(req.url)
console.log("info_path",info.path)
const filePath = path.resolve(folderPath,'./'+info.path)
console.log(filePath)
const filestream = fs.createReadStream(filePath)
filestream.pipe(res)
})
server.listen(port,()=>{
console.log("serve start")
})
编写React SSR服务
-
SSR (server side rendering)有什么特点
-
相比传统HTML模版引擎:避免重复编写代码
-
相比SPA (single page application) : 首屏渲染更快,SEO (搜索引擎优化)友好
-
缺点:
- 通常qps较低,前端代码编写时需要考虑服务端渲染情况
-
课程代码
const React = require('react')
const ReactDOMServer = require('react-dom/server')
const http = require('http')
function App(props){
return React.createElement('div',{},props.children || 'hello')
}
const serve = http.createServer((req,res)=>{
res.sendDate(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
${ReactDOMServer.renderToString(
React.createElement(App,{},'my_content')
)}
<script>
//init react application..
</script>
</body>
</html>
`)
})
const port = 3000
server.listen(port,()=>{
console.log(`server listens on:${port}`)
})
SSR难点:
-
需要处理打包代码
-
需要考虑前端的代码在服务器运行时的逻辑
- 一般放在react生命周期后面
-
移除对服务端无意义的副作用或者重置环境
适用inspector进行调试、诊断
-
V8 Inspector:开箱即用、特性丰富强大、与前端开发一致、跨平台
- node --inspect
-
场景:
- 查看console.log内容
- breakpoint
- 高CPU、死循环: cpuprofile
- 高内存占用: heapsnapshot
- 性能分析
部署简介
-
部署要解决的问题
- 守护进程:当进程退出时,重新拉起
- 多进程: cluster 便捷地利用多进程
- 记录进程状态,用于诊断
-
容器环境
- 通常有健康检查的手段,只需考虑多核cpu利用率即可