这是我参与「第四届青训营 」笔记创作活动的第14天
Node.js是一个开源和跨平台的JavaScript运行时环境。
Node.js的应用场景
1. 前端工程化:Node.js赋予了js开发者在浏览器外运行代码的能力,加速催生了这些项目的出现
2. Web服务器应用:使用Node.js开发Web服务器应用
3. Electron应用:Electron由Node.js+Chromium+Native APIs构成。它是一个得到了Node.js和基于不同平台的Native APIs加强的Chromium浏览器,可以用来开发跨平台的桌面级应用。
Node.js运行时结构
-
v8主要包含了JavaScript Runtime,诊断调试工具inspector
-
libuv:基于事件驱动的异步IO模型库,js代码发出请求,最终由libuv完成,所设置的回调函数则是在libuv触发。用于事件循环、系统调用
- 异步I/O:在Node中,绝大多数的操作都以异步的方式进行调用
- 单线程:Node保持了JavaScript在浏览器中单线程的特点,Node采用了与Web Workers相同的思路来解决单线程中大计算量的问题:child_process
- 跨平台:Node.js跨平台的特点+JS无需编译环境,使开发成本低,整体学习成本低
编写HTTP Server
编写 HTTP Server + Client
编写http_server.js
const http = require('http');
const port = 3000;
const server = http.createServer((req,res)=>{
res.end("hello");
})
server.listen(port,()=>{
console.log(`server listens on ${port}`);
})
在cmd里执行node命令,打开浏览器输入localhost:3000访问页面得到hello
编写http_server_json.js
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', () => {
// Buffer.concat——Node 缓冲区合并
const buf = Buffer.concat(bufs).toString('utf-8')
let msg = 'hello'
try {
// JSON.parse(),数据变成一个 JavaScript 对象。
const ret = JSON.parse(buf)
msg = ret.msg
} catch (error) {
// receive invalid json data
}
const responseJson = {
msg: `receive :${msg}`
}
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify(responseJson))
})
})
server.listen(port, () => {
console.log(`server listens on ${port}`);
})
编写http_client.js
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)
async await 异步操作参考:
编写静态文件服务器
编写static_server.js:在同级static文件夹中写一个index.html
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) => {
// expectede http://127.0.0.1:3000/index.html?abc=10
const info = url.parse(req.url)
// static/index.html
const filepath = path.resolve(folderPath, './' + info.path)
console.log('filepath is:',filepath);
// 更倾向于用stream API读取数据
const filestream= fs.createReadStream(filepath)
filestream.pipe(res)
})
server.listen(port, () => {
console.log(`server listens on ${port}`);
})
编写React SSR服务
SSR的难点:
- 需要处理打包代码
require('./static.style.css') - 需要思考前端代码在服务端运行时的逻辑
async componentDidMount() { const res = await fetch('http://my.server.domain') - 移除对服务端无意义的副作用,或者重置环境
使用inspector进行调试、诊断
在启动时使用node --inspect +文件名 然后open http://localhost:9229/json
场景:
- 查看console.log内容
- breakpoint
- 高CPU、死循环:cpuprofile
- 高内存占用:heapsnapshot
- 性能分析