Node.js简介
异步I/O
1、当Node.js执行I/O操作时,会在响应返回并恢复操作,而不是阻塞线程并浪费CPU循环等待
2、代码编写顺序与执行顺序无关
单线程
Node.js保持了JavaScript在浏览器中单线程的特点
优点: ①不用处处在意状态同步问题,不会发生死锁没有线程上下文切换带来的性能开销 缺点: ①无法利用多核CPU ②错误会引起整个应用退出,健壮性不足大量计算占用导致CPU,无法继续执行
浏览器为例,浏览器是多进程,JS引擎单线程 Browser进程:浏览器主进程,只有一个 插件进程:插件使用时才创建 GPU进程:最多一个用于3D绘制 渲染进程:页面渲染、JS执行、事件处理
- GUI渲染进程+
- JS引擎线程+V8
- 事件触发线程
- 定时器触发线程
- 异步请求线程
跨平台
兼容Windows和*nix平台,主要得益于在操作系统与Node上层模块系统之间构建了一层平台架构。
应用场景
Node.js在大部分领域都占有一席之地,尤其是I/O密集型的
- web应用:Express/Koa
- 前端构建:Webpack
- GUI客户端软件:VSCode/网易云音乐
- 其他:实时通讯、爬虫、CLI等...
模块化机制
1.何为模块化? 根据功能或业务将一个大程序拆分成互相依赖的小文件,再用简单的方式拼装起来
2.为什么模块化?无模块化问题
所有script标签必须保证顺序正确,否则会依赖报错全局变量存在命名冲突,占用内存无法被回收
llFE/namespace会导致代码可读性低等诸多问题
CommonJS规范
Node.js支持CommonJS模块规范,采用同步机制加载模块
①如上图所示,在greeting.js文件中定义prefix变量以及sayHi方法,在index.js文件中会输出'hello world'
②因为prefix没有在module.exports里面进行导出,也就是说在index.js里面不会拿到prefix。
③module.exports是CommonJS的一个导出规范,导出的方式就是require('./greeting')
实际上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
require.cache 中缓存着加载过的模块,缓存的原因:同步加载
1.文件模块查找耗时,如果每次require都需要重新遍历查找,性能会比较差;
2.在实际开发中,模块可能包含副作用代码
其他模块化规范
- AMD是RequireJS在推广过程中规范化产出,异步加载,推崇依赖前置;
- CMD是SeaJS在推广过程中规范化产出,异步加载.推崇就近依赖;
- UMD (Uhiversal Module Definition规范,兼容AMD和ComrnonJS模式;
- ES Modules (ESM),语言层面的模块化规范,与环境无关,可借助babel编译
ES Modules(ESM)
- ESM是在ES6语言层面提出的一种模块化标准
- ESM中主要有import、export两个关键词,不能console打印两个关键词
如何创建文件?
如果Node.js版本大于13,文件后缀可以写.mjs
Tree Shaking
如果一个已创建的方法没有的话,Tree Shaking可以把这个方法给干掉
Code Splitting
进行代码分割
CommonJS VS ESM
- CommonJS模块输出的是一个值的拷贝;ESM 模块输出的是值的引用
- CommonJS模块是运行时加载;ESM模块是编译时输出(提前加载)
包管理机制
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 代码托管地址
- 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去实现操作
在现实中遇到的层级可能会更深,就会出现回调地狱。
回调地狱的解决方法:
Promise
Promise是一个具有四个状态的有限状态机,其中三个核心状态为Pending(挂起)、Fulfiled(完成)、Rejected(拒绝)、以及还有一个未开始状态。
上一步操作中,如果用Promise操作的话,如何实现?
在Node.js16中,除了有fs/readfile,还有一个fs/promise,如何readfile会返回一个promise
如何将Callback转为Promise形式?util.promisify
await
await函数使用try catch捕获异常(注意并行处理)
可以跟promise也可以跟普通函数,不过跟普通函数没有任何区别
Event
发布订阅模式,Node.js内置events模块,比如HTTP server on('request')事件监听
Web应用开发
HTTP模块
搭建一个最简单的HTTP服务,Node.js内置HTTP模块
Koa介绍
Koa-基于Node.js平台的下一代Web开发框架
- 底层还是使用的HTTP模块,提供更优雅的函数库,编写时会更简单一些
Koa它仅仅提供了一个轻量优雅的函数库,使得编写Web应用变得得心应手,不在内核方法中任何中间件
执行过程
-
服务启动
- 实例化application
- 注册中间件
- 创建服务、监听端口
-
接受/处理请求
- 获取请求req、res对象
- req -> request、res -> response封装
- request & response -> context
- 执行中间件
- 输出设置到ctx.body 上的内容
Koa中间件
Koa应用程序是一个包含一组中间件函数的对象,它是按照葱模型组织和执行的
插洋葱:插洋葱时会从第一层插到最后一层,再从最后一层插出来到第一层
假设洋葱有三层,那么中间件的执行顺序为:1 2 3 2 1
获取处理函数的执行时间
三个中间件:
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模块
单进程较慢,出问题容易退出
多进程较快,出问题不容易退出
进程守护
Node.js进程管理工具:
多进程|自动重启|负载均衡|日志查看|性能监控
或者使用pm2进程管理与监控
复杂计算
如果一个for循环高达十亿次,那么计算时间就会超过十秒,就会阻塞后面的代码
解决方法:
使用多进程拆到computer.json里面
最后
前端开发与服务器开发的区别: