【青训营】--Node.js入门

472 阅读8分钟

Node.js简介

异步I/O

1、当Node.js执行I/O操作时,会在响应返回并恢复操作,而不是阻塞线程并浪费CPU循环等待

2、代码编写顺序与执行顺序无关 image.png

单线程

Node.js保持了JavaScript在浏览器中单线程的特点

优点: ①不用处处在意状态同步问题,不会发生死锁没有线程上下文切换带来的性能开销 缺点: ①无法利用多核CPU ②错误会引起整个应用退出,健壮性不足大量计算占用导致CPU,无法继续执行

浏览器为例,浏览器是多进程,JS引擎单线程 Browser进程:浏览器主进程,只有一个 插件进程:插件使用时才创建 GPU进程:最多一个用于3D绘制 渲染进程:页面渲染、JS执行、事件处理

  • GUI渲染进程+
  • JS引擎线程+V8
  • 事件触发线程
  • 定时器触发线程
  • 异步请求线程

跨平台

兼容Windows和*nix平台,主要得益于在操作系统与Node上层模块系统之间构建了一层平台架构。

image.png

应用场景

Node.js在大部分领域都占有一席之地,尤其是I/O密集型的

  • web应用:Express/Koa
  • 前端构建:Webpack
  • GUI客户端软件:VSCode/网易云音乐
  • 其他:实时通讯、爬虫、CLI等...

模块化机制

1.何为模块化? 根据功能或业务将一个大程序拆分成互相依赖的小文件,再用简单的方式拼装起来

2.为什么模块化?无模块化问题

所有script标签必须保证顺序正确,否则会依赖报错全局变量存在命名冲突,占用内存无法被回收

llFE/namespace会导致代码可读性低等诸多问题

CommonJS规范

Node.js支持CommonJS模块规范,采用同步机制加载模块

image.png

①如上图所示,在greeting.js文件中定义prefix变量以及sayHi方法,在index.js文件中会输出'hello world'

②因为prefix没有在module.exports里面进行导出,也就是说在index.js里面不会拿到prefix。

③module.exports是CommonJS的一个导出规范,导出的方式就是require('./greeting')

image.png

实际上module.exports是可以替换的:exports=module.exports={}

加载方式

1.加载内置模块require('fs')

2.加载相对|绝对路径的文件模块

require('/User / .../file.js')

require('./file.js')

3.加载npmrequire('lodash')

npm包查找原则:require('lodash')

1.当前目录node_modules

2.如果没有,父级目录的node_modules

3.如果没有,沿着路径向上递归,直到根目录下node_modules4.找到之后会加载package.json main指向的文件,如果没有package.json则依次查找index.js、index.json、index.node

image.png

require.cache 中缓存着加载过的模块,缓存的原因:同步加载

1.文件模块查找耗时,如果每次require都需要重新遍历查找,性能会比较差;

2.在实际开发中,模块可能包含副作用代码

image.png

其他模块化规范

  • AMD是RequireJS在推广过程中规范化产出,异步加载,推崇依赖前置;
  • CMD是SeaJS在推广过程中规范化产出,异步加载.推崇就近依赖;
  • UMD (Uhiversal Module Definition规范,兼容AMD和ComrnonJS模式;
  • ES Modules (ESM),语言层面的模块化规范,与环境无关,可借助babel编译

image.png

image.png

ES Modules(ESM)

  • ESM是在ES6语言层面提出的一种模块化标准
  • ESM中主要有import、export两个关键词,不能console打印两个关键词

image.png

如何创建文件?

如果Node.js版本大于13,文件后缀可以写.mjs

Tree Shaking

如果一个已创建的方法没有的话,Tree Shaking可以把这个方法给干掉

Code Splitting

进行代码分割

CommonJS VS ESM

  • CommonJS模块输出的是一个值的拷贝;ESM 模块输出的是值的引用
  • CommonJS模块是运行时加载;ESM模块是编译时输出(提前加载) image.png

包管理机制

npm介绍

NPM是Node.js中的包管理器,提供了安装、删除等其他命令来管理包

  • 一个包可以require很多的模块
  • 模块可以包含多个包
  • 两者是多对多的

常用命令

  • npm init 生成一个package.json框架,让交互式的方式填写信息

  • npm config

    设置代理,设置联名

  • npm run[cmd]

  • npm install [pkg]

  • npm uninstall [pkg]

    上述三个:可以对安装卸载更新某个包

  • npm info [pkg]

    查看包信息

  • npm publish

    发到包服务器,供公共使用

内容

  • name包名称
  • version版本号
  • main入口文件
  • scripts 执行脚本
  • dependencies线上依赖
  • devDependencies开发依赖
  • repository 代码托管地址

image.png

更多package.json配置

  • dependencies 业务依赖,应用发布后正常执行所需要的包
  • devDependencies开发依赖,只用于开发环境
  • peerDependencies同等依赖,比如一个webpack 插件依赖特定版本的 webpack
  • bundledDependencies打包依赖(npm run pack),必须已经在 devDep或者dep声明过
  • optionalDependencies可选依赖

私有npm

  • 镜像公司内部私有npm
  • 镜像设置npm config set registry=bnpm.byted.org

其他

  • 并行安装

  • 扁平管理

  • 锁文件(lockfile)

    俩npm包版本不同会锁文件

  • 缓存优化

  • npm7|yarn => lock/扁平/缓存

  • pnpm => monorepo/硬、符号链接/安全性高

异步编程

异步编程的方式有四种:

callback|pormise|async|event

Callback

目的:读取package.json中main字段对应的文件内容

如果main里面又index.js的文件,就会去读取index.js文件,如何Node.js提供的API去实现操作

image.png

在现实中遇到的层级可能会更深,就会出现回调地狱。

回调地狱的解决方法:

Promise

Promise是一个具有四个状态的有限状态机,其中三个核心状态为Pending(挂起)、Fulfiled(完成)、Rejected(拒绝)、以及还有一个未开始状态。

image.png

上一步操作中,如果用Promise操作的话,如何实现?

在Node.js16中,除了有fs/readfile,还有一个fs/promise,如何readfile会返回一个promise

image.png

如何将Callback转为Promise形式?util.promisify

image.png

await

await函数使用try catch捕获异常(注意并行处理)

image.png

可以跟promise也可以跟普通函数,不过跟普通函数没有任何区别

Event

发布订阅模式,Node.js内置events模块,比如HTTP server on('request')事件监听

image.png

Web应用开发

HTTP模块

搭建一个最简单的HTTP服务,Node.js内置HTTP模块

image.png

Koa介绍

Koa-基于Node.js平台的下一代Web开发框架

  • 底层还是使用的HTTP模块,提供更优雅的函数库,编写时会更简单一些

Koa它仅仅提供了一个轻量优雅的函数库,使得编写Web应用变得得心应手,不在内核方法中任何中间件

image.png

执行过程

  • 服务启动

    • 实例化application
    • 注册中间件
    • 创建服务、监听端口
  • 接受/处理请求

    • 获取请求req、res对象
    • req -> request、res -> response封装
    • request & response -> context
    • 执行中间件
    • 输出设置到ctx.body 上的内容

image.png

Koa中间件

Koa应用程序是一个包含一组中间件函数的对象,它是按照葱模型组织和执行的

插洋葱:插洋葱时会从第一层插到最后一层,再从最后一层插出来到第一层

image.png

假设洋葱有三层,那么中间件的执行顺序为:1 2 3 2 1

image.png

获取处理函数的执行时间

image.png

三个中间件:

1、logger中间件

首先等待后面的函数执行完,执行完之后,response会映射到ctx,任何就可以得到第三个函数的执行时间

2、response中间件

开始之前会打印一个开始时间,await next相当于等待下一个中间件执行完成,执行完成后,会再打印一个结束时间,映射到ctx的一个变量上去。

3、函数执行

for循环,简单函数

常用中间件

  • Koa-router:路由解析
  • koa-body:reques body 解析
  • koa-logger:日志记录
  • koa-views:模板渲染
  • koa2-cors:跨域处理
  • koa-session:session处理
  • koa-helmet:安全防护

Koa中间件种类繁多,质量参差不齐,需要合理选择,搞笑组合。。。

基于Koa 的前端框架

开源:Think JS/Egg

内部:Turbo、Era、Gulu

  • Koa对象response / request / context / application等扩展
  • Koa常用中间件库
  • 公司内部服务支持
  • 进程管理
  • 脚手架
  • ...

线上部署

多进程|进程守护|复杂计算

Node.js 保持了JavaScript,在浏览器中单线程的特点(一个进程只开一个线程)

Node.js虽然是单线程模型,但是其基于事件驱动、异步非阻塞模式,可以应用于高并发场景,同时避免了线程创建、线程之间上下文切换所产生的资源开销。

缺点:

  • 无法利用多核CPU
  • 错误会引起整个应用退出,健壮性不足
  • 大量计算占用导致CPU,无法继续执行

利用多核CPU

Node.js提供了cluster/child——process模块

image.png

单进程较慢,出问题容易退出

多进程较快,出问题不容易退出

进程守护

Node.js进程管理工具:

多进程|自动重启|负载均衡|日志查看|性能监控

image.png image.png

或者使用pm2进程管理与监控 image.png

复杂计算

如果一个for循环高达十亿次,那么计算时间就会超过十秒,就会阻塞后面的代码

image.png

image.png

解决方法:

使用多进程拆到computer.json里面

image.png

最后

前端开发与服务器开发的区别:

image.png