字节前端青训营课程内容笔记
编写 HTTP Server
基本的 http server:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const http = require('http')
const port = 3000
const server = http.createServer((req, res) => { res.end('hello world') })
server.listen(port, () => { console.log('listen on :', port) })
|
发送 json 数据的 http server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| 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', () => { let buf = Buffer.concat(bufs).toString('utf8') let msg = 'Hello' try { const ret = JSON.parse(buf) msg = ret.msg } catch (err) { } const responseJson = { msg: `receive: ${msg}`, } res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify(responseJson)) console.log('已经向客户端发送数据') }) }) server.listen(port, () => { console.log('listen on:', port) })
|
在此,需要一个客户端发送响应,才能看到结果,所以,我们接下来创建一个发送数据的客户端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| const http = require('http') const port = 3000
const body = JSON.stringify({ msg: '我是来自客户端的数据', })
const request = http.request( 'http://127.0.0.1:3000', { method: 'POST', headers: { 'Content-Tpye': 'application/json', }, }, (response) => { const bufs = [] response.on('data', (buf) => { bufs.push(buf) }) response.on('end', () => { const buf = Buffer.concat(bufs).toString('utf8') const json = JSON.parse(buf) console.log('json.msg', json) }) } )
request.end(body)
|
结合 promise 创建一个返回 json 的 http server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| const http = require('http'); const port = 3000
const server = http.createServer(async (req, res) => {
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', () => { let msg = 'hello' const buf = Buffer.concat(bufs).toString('utf8') try { const ret = JSON.parse(buf) msg = ret.msg } catch (err) { reject(err) } resolve(msg) }) }) const responseJson = { msg: `receive msg: ${msg}` } res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify(responseJson)) })
server.listen(port, () => { console.log('listen on: ', port) })
|
发送静态文件的 htpp server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const http = require('http') const fs = require('fs') const url = require('url') const path = require('path')
const port = 3000
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) })
server.listen(port, () => { console.log('listen on: ', port) })
|
注意
- path.resolve([…paths])里的每个参数都类似在当前目录执行一个 cd 操作,从左到右执行,返回的是最后的当前目录。所以 const filePath = path.resolve(folderPath, info.path)并不会正确地找到文件所在的路径。
- 使用 pipe 会节省内存
编写 http server-React SSR
SSR (server side rendering)有什么特点?
- 相比传统 HTML 模版引擎:避免重复编写代码
- 相比 SPA (single page application):首屏渲染更快,SEO 友好
- 缺点:通常 qps 较低,前端代码编写时需要考虑服务端渲染情况
SSR 难点:
- 需要处理打包代码
- 需要思考前端代码在服务端运行时的逻辑
- 移除对服务端无意义的副作用,或重置环境
SSR(Server Side Rendering)相比于传统的 HTML 模板引擎,能够比避免重复编写代码,相比于 SPA,首屏渲染更快、SEO 友好;其缺点是 QPS 较低,需要考虑服务器的渲染性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| const React = require('react') const ReactDOMServer = require('react-dom/server') const http = require('http')
const port = 3000
function App(props) { return React.createElement('div', {}, props.children || 'hello') }
const server = http.createServer((req, res) => { res.end( ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> ${ReactDOMServer.renderToString(App({}))} </body> </html> ` ) })
server.listen(port, () => { console.log('listen on:', port) })
|
注意
- SSR 需要处理打包代码,如使用 webpack
- 需要思考在服务器端运行时的逻辑,如在 componentDidMount 的时候发送网络请求
- 移除对服务器无意义的副作用配置和环境