Node.js与前端开发实战 | 青训营笔记

88 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第6天

认识Node.js

  • Node.js 是一个开源和跨平台的 JavaScript 运行时环境。 它几乎是任何类型项目的流行工具!
  • Node.js 在浏览器之外运行 V8 JavaScript 引擎(Google Chrome 的内核)。 这使得 Node.js 的性能非常好。Node.js 应用程序在单个进程中运行,无需为每个请求创建新的线程。
  • Node.js 在其标准库中提供了一组异步的 I/O 原语,以防止 JavaScript 代码阻塞,通常,Node.js 中的库是使用非阻塞范式编写的,使得阻塞行为成为异常而不是常态。当 Node.js 执行 I/O 操作时(比如从网络读取、访问数据库或文件系统),Node.js 将在响应返回时恢复操作(而不是阻塞线程和浪费 CPU 周期等待)。这允许 Node.js 使用单个服务器处理数千个并发连接,而不会引入管理线程并发(这可能是错误的重要来源)的负担。
  • Node.js 具有独特的优势,因为数百万为浏览器编写 JavaScript 的前端开发者现在无需学习完全不同的语言,就可以编写除客户端代码之外的服务器端代码!

Node.js的应用场景

  • 前端工程化
    • Bundle(构建):webpack,vite,esbuild,parcel
    • Uglify:uglifyjs
    • Transpile(语法转换):bablejs,typescript
    • 其他语言加入竞争:esbuild,parcel,prisma
    • 现状:虽然有这些其他语言的加入,但node.js在前端工程化中还是处于难以替代的地位,因为本身这些前端工程化的工具都是为了前端开发者服务的,既然这里的工具用户是前端开发者,那么大部分工具的开发者是偏向于前端开发,对于前端开发者而言,node.js相比于其他后端语言学习成本是更低的。所以在前端工程化里面,node.js还是处于难以替代的地位。哪怕你是属于纯前端开发,你也会经常使用node.js去开发这些工具。
  • Web服务端应用
    • 学习曲线平缓,开发效率较高
    • 运行效率接近常见的编译语言
    • 社区生态丰富工具链成熟(npm,V8 inspector)
    • 与前端结合的场景会有优势(SSR)
    • 现状:竞争激烈,Node.js有自己独特的优势
  • Electron跨端桌面应用
    • 商业应用:vscode,slack,discord,zoom
    • 大型公司内的效率工具
    • 现状:大部分场景在选型的时候都值得考虑
  • Node.js在字节
    • BFF应用、SSR应用,距离:Modern.js
    • 服务端应用:头条搜索,西瓜视频,懂车帝
    • Electron应用:飞连,飞书
    • 每年新增1000+Node.js应用

Node.js运行时结构

  • V8:JavaScript Runtime,诊断调试工具(inspector)
  • libuv:eventLoop(事件循环),syscall(系统调用)

用 node-fetch 发起请求时,首先通过npm安装node-fetch模块,之后在用户代码里面调用node-fetch模块,这些代码会在V8中执行,那么node-fetch执行是调用底层http模块(Node.js Core(JavaScript)),再去调用更底层的Node.js Core(c++),之后可能调用llhttp去做http的序列化与反序列化,然后把得到的数据再通过libuv,可能调用TCP连接,再把这个数据发给远端,远端返回数据,在事件循环中得到这个数据,在把拿到的数据给llhttp解析出来,得到的数据返回给Node.js Core(JavaScript),最后送到用户代码从而得到最终的数据。

Node.js的安装

  • Mac,Linux推荐使用nvm。多版本管理
  • Windows nvm4w 或官方安装包

编写静态文件服务

  • 静态文件服务

    • 与高性能可靠的服务相比还差什么
      • CDN:缓存+加速

      • 分布式存储,容灾

    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)=>{

    //期望收到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)
    
    //stream风格api的好处:内部做了处理,占用尽可能少的空间,按需返回给client
    
    const filestream = fs.createReadStream(filepath)
    
    filestream.pipe(res)
    

    }) const port = 3000 server.listen(port,()=>{ //成功监听,触发回调函数 console.log(server listens on: ${port}) })