node
为什么要学习Node.js
- 企业需求 +具有服务器开发经验更好 +front-end (前端) +back-end(后端) +全栈开发工程师 +基本的网站开发能力 *服务端 *前端 *运维部署
学习Node.js的目的可以更好帮助大家打开服务端这个黑盒 只有懂了解服务器才能更好的配合服务端开发人员进行开发 node对于前端来讲是进阶高级前端开发工程师必备的技能 web后台服务器 1、Java 2、PHP 3、Python 4、Ruby 5、Node.js 6、.............
什么是服务端
服务端主要负责接收客户端的请求,并提供相应的服务或资源。它可以执行各种任务,如处理业务逻辑、访问数据库、生成动态内容、处理文件上传和下载等
Node.js是什么
Node.js 用于在服务器端运行 JavaScript 代码
- Node.js不是一门语言
- Node.js不是库,不是框架
- Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 [Node.js是一个JavaScript运行时的环境(平台)] Google Chrome的V8引擎是目前公认的解析执行JavaScript代码最快的 node.js的作者把Google Chrome中的V8引擎移植了出来,开发了一个独立的JavaScript运行时环境
- 简单来讲就是Node.js可以解析和执行JavaSript代码
- 以前只有浏览器可以解析执行JavaScript代码
- 也就是说现在的JavaScript可以完全脱离浏览器来运行,一切都归功与Node.js
- 利用事件驱动、非阻塞和异步IO
- event-driven 事件驱动
- non-blocking I/O model 非阻塞IO模型(异步)
- lightweight and efficient 轻量和高效
- npm是世界上最大的开源库生态系统,npm是基于Node.js开发的包管理工具
- 绝大多数JavaScript相关的包都存放在了npm上
- Node 应用由模块组成,采用 CommonJS 模块规范
- Node的顶层对象是global,js的顶层对象是window
什么是V8?
V8是Google的开源高性能JavaScript和WebAssembly引擎,用C ++编写。它用于Chrome和Node.js等。它实现ECMAScript和WebAssembly,并在Windows 7或更高版本,macOS 10.12+以及使用x64,IA-32,ARM或MIPS处理器的Linux系统上运行。V8可以独立运行,也可以嵌入到任何C ++应用程序中。
- V8 是一个 JavaScript 引擎
- Node.js 自己并不会直接执行 JavaScript,真正负责“看懂并执行 JS 代码”的核心,就是 V8。
浏览器中的JavaScript
- 浏览器中的JavaScript是没有文件操作的能力的
- ECMAScript(js的基本语法)
- BOM(浏览器对象模型)
- DOM(浏览器对象模型)
Node.js中的JavaScript
- 在node环境不能使用window对象,window对象是浏览器专属
- 没有BOM、没有DOM
- ECMAScript
- Node中的JavaScript具有文件操作的能力
- 在Node这个JavaScript执行环境中为JavaScript中提供了一些服务器级别的操作API
- 例如文件的读写
- 网络服务的构建
- 网络通信
- Http服务器
- 等处理.........
node解决什么需求?
1、参考:https://www.cnblogs.com/laoyuming/p/14287504.html
前端工程化
- 搭建脚手架
- webpack方面的优化,打包速度等
中间层
中间层就是在浏览器和服务端之间加了一层
传统的是:原来客户端直接向 Server发送请求,Server层收到请求后经过计算处理将结果返回给浏览器.
现在加入中间层: 浏览器将请求发送给node层,node层经过一轮处理后再向Server层【如java等后台接口】发起请求,Server层处理完毕将响应结果返回给node层,node层最后将数据处理后返回给浏览器.
好处:
- 减轻客户端内存
- SEO性好,有利于网页被搜索到
代理转发
- http-proxy-middleware中间件
浏览器首先将请求发送给 node服务器,请求收到后 node服务器可以对请求做一些处理,比如将原来的路径变换一下,请求头的信息改变一下,(请求的信息改变一下),再把修改后的请求发送给远程真实的服务器.
服务器计算出响应结果再返回给node服务器,node服务器仍然可以对响应做选择性处理再分返回给浏览器
- 代理转发:可以解决前端跨越的问题
服务端渲染SSR 【页面性能优化和SEO搜索引擎优化】
- 单页面应用,经常会碰到首屏加载性能问题,接了中间层nodejs的话,那么我们可以把首屏渲染的任务交给nodejs去做,node去做服务端渲染,优化了SEO搜索引擎优化
- 服务端渲染,服务端把需要的数据处理好和模板拼接好返回给客户端去显示 (客户端就不再需要额外处理数据再渲染了)
- 客户端拿到手的,是可以直接渲染然后呈现给用户的 HTML 内容,不再需要为了生成DOM内容,而在js处理数据拼接等再去渲染页面
- 服务端渲染是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的
- 减少了请求的次数
- 服务端渲染的话,服务端只请求一次
- 客户端渲染的话,最少两次请求,如客户端发起请求,服务端把页面(响应的是字符串)HTML返回给客户端,客户端从上到下依次解析,如果在解析的过程中(对数据进行计算和拼接),发现ajax请求,再次像服务器发送新的请求,客户端拿到ajax 响应结果,模板引擎渲染
CSR : 客户端渲染(Client Side Render) SSR:服务端渲染(Server Side Render)
云函数
为什么需要Node中间层
参考:https://zhuanlan.zhihu.com/p/51160124
目前很多一线大厂比如淘宝、Facebook(php写的中间层)都已经在使用了Node做中间层。 Node中间层的优点有:
- 减轻客户端内存,项目用户体验好;
- API代理和数据转发:Node.js中间层可以作为API代理,将前端应用程序的请求转发到后端API服务器。这对于解决跨域请求、数据格式转换、数据聚合和数据预处理等问题非常有用。
- 数据转换和格式化:Node.js中间层可以在前端应用程序和后端服务之间进行数据的转换和格式化。例如,它可以将数据库中的原始数据进行处理和转换,以符合前端应用程序的需求
- 有利于SEO
- 有利于网页被搜索到
- node可以解决seo,用node做服务端渲染
node优缺点
优点
- 处理高并发场景性能更佳
- 适合I/O密集型应用,指的是应用在运行极限时,CPU占用率仍然比较低,大部分时间是在做 I/O硬盘内存读写操作
缺点
因为Nodejs是单线程,带来的缺点有:
- 不适合CPU密集型应用
- 只支持单核CPU,不能充分利用CPU
- 可靠性低,一旦代码某个环节崩溃,整个系统都崩溃
node作为后台的优劣势?相比Java,PHP或者Go
- PHP 处理高并发的能力比较一般,因为多进程非常损耗服务器资源;其次 PHP 作为服务端渲染在研发方面非常低效,前端代码需要融合 PHP 代码,而现在前端也淘汰了这类技术方案
- C++ 作为后台服务性能虽高,但是在研发效率上是比较低的,要不断进行编译调试,根本无法跟上运营与项目需求的进度。
- Java具有多线程处理,一个单独的线程处理一个任务,多线程可以允许不排队的情况下同时执行多个任务
- Node单线程
- 在 Java、PHP 或者 .net 等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约 2MB 内存,而node通过非阻塞
I/O、事件驱动机制,一个 8GB 内存的服务器,可以同时处理超过 4 万用户的连接
- 在 Java、PHP 或者 .net 等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约 2MB 内存,而node通过非阻塞
- 单线程和非阻塞 I/O:Node.js 采用单线程事件循环模型,通过异步非阻塞 I/O 操作,能够高效处理大量并发请求
- 共享前端js生态
- 用node主要原因,业务场景不是特别复杂,用node能解决大部分的场景,一些数据量大业务复杂有用java,node做中间层转发,而且node对于前端容易上手,提供后端服务开发成本比较低
- 从人力资源上,如果公司中级前端以上人数大于后端,可以考虑使用nodejs来作为服务端
哪些场景不适用于node?
- 大文件读写处理,有时会使用 Node.js 服务来处理 Excel,但是遇到 Excel 过大时,会导致 Node.js 内存溢出,因为 V8 内存上限是 1.4 G
Node.js能学到啥东西
- B/S编程模型
- Browser/Server (浏览器/服务器)
- back-end
- 任何服务端技术这种BS编程模型都是一样,和语言无关
- 模块化编程
- RequireJS
- SeaJS
- @import '文件路径'
- 以前认知的JavaScript只能通过script标签来加载,在Node中可以像@import '文件路径'
- 来加载JavaScript脚本文件
- Node常用API
- 异步编程
- 回调函数
- Promise
- async
- generator
- Express开发框架 (基于 Node.js平台 Web 开发框架)
- EcmaScript6
- 学习Node不仅会帮助打开服务器黑盒,同时还会帮助学习以后的前端框架高级内容(vue.js,reactjs,angularjs)
- 。。。。
node的MVC层
- Model层主要是做一些数据库的操作
- Controller层
- 业务逻辑,处理后返回相应的结果,将数据渲染到View层
- 控制页面流转、控制业务模块调度。
- view层是数据和模板生成响应内容
异步I/O和事件驱动
异步I/O
I/O 即Input/Output, 输入和输出的意思。在浏览器端,只有一种 I/O,那就是利用 Ajax 发送网络请求,然后读取返回的内容,这属于 网络I/O。回到 nodejs 中,其实这种的 I/O 的场景就更加广泛了,主要分为两种:
- 文件 I/O。比如用 fs 模块对文件进行读写操作。
- 网络 I/O。比如 http 模块发起网络请求。
事件驱动
事件驱动就是当进来一个新的请求的时,请求将会被压入一个事件队列中,然后通过一个循环来检测队列中的事件状态变化,如果检测到有状态变化的事件,那么就执行该事件对应的处理代码,一般都是回调函数 比如读取一个文件,文件读取完毕后,就会触发对应的状态,然后通过对应的回调函数来进行处理
单线程的优势和弊端?
线程和进程的关系?
一个进程运行时产生多个线程 比如腾讯管家,腾讯管家本身就是一个程序,即就是一个进程,它里面有很多个功能,即每个功能就对应一个线程, 如果按照单线程的话,如果你要清理垃圾和病毒查杀,必须完成其中一件事,才能做下一件事,这里面是有一个执行顺序的 如果按照多线程的话,我们可以在清理垃圾的时候,同时也可以进行病毒查杀,这就是同一时刻进行,没有执行上的先后顺序
优势:
- 单线程带来的好处,操作系统完全不再有线程创建、销毁的时间开销
弊端:
- 无法利用多核 CPU
- 错误会引起整个应用退出无法继续调用异步
I/O - 大量计算占用 CPU 导致无法继续调用异步
I/O
弊端 1:解决方案
- (1)一些管理工具比如
pm2,forever等都可以实现创建多进程解决多核 CUP 的利用率问题。 - (2)在 v0.8 版本之前,实现多进程可以使用
child_process - (3)在 v0.8 版本之后,可以使用
cluster模块,通过主从模式,创建多个工作进程解决多核 CPU 的利用率问题。
弊端 2:解决方案
- (1)Nnigx 反向代理,负载均衡,开多个进程,绑定多个端口;
- (2) 一些管理工具比如
pm2,forever等都可以实现进程监控,错误自动重启等 - (3)开多个进程监听同一个端口,使用 Node 提供的
cluster模块; - (4)未出现
cluster之前,也可以使用child_process,创建多子线程监听一个端口。 - (5)这里说明下,有上面的这些解决方案,但是写 node 后端代码的时候,异常抛出
try catch显得格外有必要。
弊端 3:解决方案
- (1)可以把大量的密集计算像上面一样拆分成多个子线程计算
- 但是如果不允许拆分,想计算 100 万的大数据,在一个单线程中,Node 确实显得无能为力,这本身就是 V8 内存限制的弊端。
Node.js 能否充分利用多核处理器
- (默认的)Node.js 应用程序总是单线程的,即使在多核处理器上运行,应用程序也能只使用一个处理器。
- 但是 Node.js 的核心模块之一 Cluster 支持 Node.js 应用程序开启多核,允许我们创建多个工作进程,这些进程可以在多个内核上并行运行,并共享一个端口来侦听事件。
- 每个进程使用 IPC 与主线程通信,并根据需要将服务器句柄传递给其他进程。主进程可以侦听端口本身并以循环方式将每个新连接传递给子进程,也可以将端口分配给子进程以便子进程侦听请求。
Nodejs单线程为什么能支持高并发?
1、参考:https://zhuanlan.zhihu.com/p/61807318 Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于我们在多核 cpu 的系统上创建多个子进程,从而提高性能
- 事件循环机制,和线程池实现来处理并发
为什么基于事件驱动的服务器能实现并发
- 什么是事件驱动?
- 事件:简单的来说 就是你点了什么按钮即产生什么事件,电脑执行什么操作(调用什么函数)
- 事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理
node应用内存泄漏如何解决?
导致内存泄漏有主要以下几点:
- 全局变量没有手动销毁,因为全局变量不会被回收
- 闭包:闭包中的变量被全局对象引用,则闭包中的局部变量不能释放
- 监听事件添加后,没有移除,会导致内存泄漏
那如何检测内存泄露?
- 通过内存快照,可以使用node-heapdump 官方文档获得内存快照进行对比,查找内存溢出
- https://github.com/bnoordhuis/node-heapdump
- heap:堆,dump垃圾
- 可视化内存泄漏检查工具 Easy-Monitor [官方文档](
node的事件循环和浏览器的事件循环的区别?
node的事件循环顺序:
- timers 定时器阶段:这个阶段执行 timer(setTimeout、setInterval)的回调
- I/O callbacks 阶段:处理上一轮循环中的未执行的 I/O 回调
- idle, prepare 阶段:仅 node 内部使用
- poll 阶段:poll轮询,检索新的I/O事件,执行与I/O相关的回调
- check 阶段:执行 setImmediate() 的回调函数
- close callbacks 阶段:执行关闭请求的回调函数,比如 socket.on('close', ...) 【执行 socket 的 close关闭事件回调】
主要区别就是 【注意是node 版本11之前是存在区别!】
- Node 端,微任务在事件循环的各个阶段之间执行
- 在 node 11 版本之前,只有全部执行了 timers 阶段队列的全部任务才执行微任务队列
- 浏览器端,微任务在宏任务执行完之后执行 【宏任务执行完之后再清空微任务队列】
在node版本11以后,node和浏览器的事件循环event loop已经统一了!!
什么情况会把node版本升级?
- 使用新的ES语法,新的ES语法可能在老的node版本不支持
- 考虑webpack,如果想要webpack打包速度变快,就可以尝试升级node版本
- 一般来说新版本node运行webpack打包会比老版本node运行webpack快
如何做版本的升级,为什么要使用nvm?
- 如果你直接升级当前电脑node版本的话,那当前电脑只能安装一个node版本
- 如果有好几个node项目,每个项目node版本可能不一样,那么每次都重新安装对应的node版本去开发项目,那么是很不方便的
- nvm允许安装多个node版本,是node版本的管理工具
如何在node运行 ES6模块?
- Node.js 要求 ES6 模块采用.mjs后缀文件名。也就是说,只要脚本文件里面使用import或者export命令,那么就必须采用.mjs后缀
Node.js 遇到.mjs文件,就认为它是 ES6 模块,默认启用严格模式,不必在每个模块文件顶部指定"use strict"
- 如果不希望将后缀名改成
.mjs,可以在项目的package.json文件中,指定type字段为module。
一些资源
- 《深入浅出Node.js》
- 朴(piáo)灵
- 偏理论,几乎没有任何实战内容
- 理解原理底层有帮助
- 《Node.js权威指南》
- API讲解
- 也没有业务,没有实战
- Node入门
- Node官方API文档
- Node官方文档
- CNODE社区 ------分享、交流、资源
- CNODE-新手入门
node框架比较
express/koa/egg
Express
Express通过回调函数实现异步,在多个回调、多个中间件中写起来容易逻辑混乱,造成回调地狱问题Koa通过async/await使用同步的写法来处理异步,明显好于callback和promise。
- 中间件模型,Express是线性模型,koa是洋葱模型
- 对于响应机制,Express会立刻响应,而koa需要等中间件执行完之后才响应
Koa
- 轻量级: Koa相对于Express来说更加轻量级,它在核心提供了更少的功能,而通过中间件来实现更多的功能
- 优雅的错误处理:Koa内置了异常处理机制,可以更好地处理错误和异常,避免了回调地狱
Egg:
- egg是一个企业级的Node.js框架,对koa进一步封装
- 提供了一整套约定规范,定义了从配置、路由、扩展、中间件到控制器
- koa缺少约定规范,egg按照约定规范进行开发
如何管理node
- nvm、n
nvm
n
- https://www.npmjs.com/package/n
- n不支持windows
安装
npm install -g n
- 利用 n 下载所需node
n 版本号
- 下载最新版本
n latest
- 删除某个版本
n rm 4.4.4
fnm
- https://github.com/Schniz/fnm
- 全平台都支持,用Rust开发