update: Node.js 科普

This commit is contained in:
qianguyihao 2020-06-18 14:35:38 +08:00
parent a3e08516f6
commit 8761b57743
3 changed files with 183 additions and 105 deletions

View File

@ -8,13 +8,13 @@
Node 的重要性已经不言而喻很多互联网公司都已经有大量的高性能系统运行在 Node 之上Node 凭借其单线程异步等举措实现了极高的性能基准此外目前最为流行的 Web 开发模式是前后端分离的形式即前端开发者与后端开发者在自己喜欢的 IDE 上独立进行开发然后通过 HTTP 或是 RPC 等方式实现数据与流程的交互这种开发模式在 Node 的强大功能的引领下变得越来越高效也越来越受到各个互联网公司的青睐
### 前端同学为什么要学习后台开发
### 前端同学为什么要学习后/后端同学为什么要学习前端
- 了解前后端交互流程
- 能够和后台开发的程序员更佳紧密地结合更顺畅地沟通
- 前端同学能够和后台开发的程序员更佳紧密地结合更顺畅地沟通
- 当网站的业务逻辑需要前置时前端人员需要学习一些后台开发的技术以完成相应的任务
- 当网站的业务逻辑需要前置时前端人员需要学习一些后台开发的技术以完成相应的任务反过来也一样
- 拓宽知识视野和技术栈能够站在全局的角度审视整个项目
@ -28,47 +28,42 @@ Node 的重要性已经不言而喻,很多互联网公司都已经有大量的
3Node.js 性能高生态系统活跃提供了大量的开源库
4Jeff Atwood 2007 年提出了著名的 Atwood 定律**任何能够用 JavaScript 实现的应用系统最终都必将用 JavaScript 实现**如果你不知道 Jeff Atwood 是谁他是 Stack Overflow 网站的创始人这不重要重要的是这条定律
4Jeff Atwood 2007 年提出了著名的 Atwood 定律**任何能够用 JavaScript 实现的应用系统最终都必将用 JavaScript 实现** Jeff Atwood 是谁不重要他是 Stack Overflow 网站的联合创始人重要的是这条定律
### 后端同学为什么要学 Node.js
因为前端同学在学 Node.js
## Node.js 的介绍
## 什么是 Node.js
### 什么是 Node.js
### 官方定义
[Node.js](https://nodejs.org/zh-cn/) 是一个基于 **Chrome V8** 引擎的 JavaScript 运行环境。Node.js 使用了一个**事件驱动**、**非阻塞式 I/O**的模型 Node.js 的特性),使其轻量又高效。Node.js 的包管理工具 npm 是全球最大的开源库生态系统。
[Node.js](https://nodejs.org/zh-cn/) 是一个基于 **Chrome V8 引擎**的 JavaScript 运行环境。Node.js 使用了一个**事件驱动**、**非阻塞式 I/O**的模型使其轻量又高效。Node.js 的包管理工具 npm 是全球最大的开源库生态系统。
![](http://img.smyhvae.com/20180301_1540.png)
Node.js 不是一门语言也不是 JavaScript 的框架也不是像Nginx一样的Web服务器 **Node.js JavaScript 在服务器端的运行环境平台**
如上图所示
- Node.js 不是一门语言也不是 JavaScript 的框架也不是像 **Node.js JavaScript 在服务器端的运行环境平台**
- Node.js 内部采用 Google Chrome V8 引擎作为 JavaScript 语言解释器同时结合自行开发的 libuv 扩展了 JS 在后端的能力使得 JS 既可以在前端进行 DOM 操作浏览器端又可以在后端调用操作系统资源I/O 操作文件读写数据库操作等是目前最简单的全栈式语言
备注 1[V8 引擎](https://v8.dev/) 本身是用 C++ 写的。 [libuv](https://zh.wikipedia.org/wiki/Libuv) 这个库本身也是用 C/C++ 写的。
备注 2限制语言能力的不是语言本身而是语言的生态
### Node.js 的组成
Node.js 里运行 JavaScript跟在 Chrome 里运行 JavaScript 有什么不同
二者采用的是同样的 JS 引擎 Node.js 里写 JS和在前端写 JS几乎没有不同在写法上的区别在于Node.js 没有浏览器页面标签相关的 API但是新增了一些 Node.js 相关的 API通俗来说对于开发者而言在前端写 JS 是用于控制浏览器 Node.js 环境写 JS 可以控制整个计算机
我们知道JavaScript 的组成分为三个部分
- ECMAScript
- DOM
- DOM标签元素相关的API
- BOM
- BOM浏览器相关的API
ECMAScript JS 的语法DOM BOM 浏览器运行环境JS 提供的 API
ECMAScript JS 的语法DOM BOM 浏览器JS 提供的 API
Node.js 的组成分为
- **ECMAScript**ECMAScript 的所有语法在 Node 环境中都可以使用
- **Node 环境**提供的一些**附加 API**(包括文件网络路径等等 API)
- **Node 环境**提供的一些**附加 API**(包括文件网络等相关的 API)
如下图所示
@ -76,10 +71,47 @@ ECMAScript 是 JS 的语法DOM 和 BOM 浏览器运行环境为 JS 提供的
### 补充
PHPJSPPythonPerlRuby 既是语言也是平台不同Node.js 的使用 JavaScript 进行编程运行在 Chrome V8 引擎上
PHPJSP 等相比PHPJSP.net 都需要运行在服务器程序上ApacheNginxTomcatIIS
Node.js 跳过了 ApacheNaginxIIS HTTP 服务器它自己不用建设在任何服务器软件之上Node.js 的许多设计理念与经典架构LAMP = Linux + Apache + MySQL + PHP有着很大的不同可以提供强大的伸缩能力Node.js 没有 web 容器
JS 语言非常灵活使得它在严谨性方面不如 Java 等传统的静态语言JS 是一门动态语言而且融合了面向对象和函数式编程这两种编程范式
随着 ES6ES7 JS 语法规范的出现以及浏览器对这些规范的支持使得我们可以用更为现代化的 JS 语言特性来编写现代化的应用
## Node.js 的架构和依赖
Node.js 的架构如下
![](http://img.smyhvae.com/20180301_1540.png)
Node.js 内部采用 Google Chrome V8 引擎作为 JavaScript 语言解释器同时结合自行开发的 libuv **扩展了 JS 在后端的能力比如 I/O 操作文件读写数据库操作等**使得 JS 既可以在前端进行 DOM 操作浏览器前端又可以在后端调用操作系统资源是目前最简单的全栈式语言
其次Node 生态系统活跃提供了大量的开源库使得 JavaScript 语言能与操作系统进行更多的交互
### Node.js 运行环境的核心V8 引擎 libuv
Node.js JavaScript 在服务器端的运行环境在这个意义上Node.js 的地位其实就是 JavaScript 在服务器端的虚拟机类似于 Java 语言中的 Java 虚拟机
- [V8 引擎](https://v8.dev/) :编译和执行 JS 代码、管理内存、垃圾回收。V8 给 JS 提供了运行环境,可以说是 JS 的虚拟机。V8 引擎本身是用 C++ 写的。
- [libuv](https://zh.wikipedia.org/wiki/Libuv) libuv 是一个专注于异步 I/O 的跨平台类库,目前主要在 Node.js 上使用。它是 Node.js 最初的作者 Ryan Dahl 为 Node.js 写的底层类库也可以称之为虚拟机。libuv 本身是用 C 写的。
### Java 虚拟机和 V8 引擎是由同一人开发
Chrome 浏览器成功的背后离不开 JS V8 引擎作为虚拟机V8 的性能表现优异它的开发者是 Lars Bak Lars 的工作履历里绝大部分都是与虚拟机相关的工作在开发 V8 之前他曾经在 Sun 公司工作担任 HotSpot 团队的技术领导主要致力于开发高性能的 Java 虚拟机在这之前他也曾为 SelfSmalltalk 语言开发过高性能虚拟机这些无与伦比的经历让 V8 一出世就超越了当时所有的 JS 虚拟机
![](http://img.smyhvae.com/20200617_1120.png)
V8 的性能优势使得用 JavaScript 写高性能后台服务程序成为可能在这样的契机下Ryan Dahl 选择了 JavaScript选择了 V8在事件驱动非阻塞 I/O 模型的设计下实现了 Node
### V8 的内存限制
在一般的后端开发语言中在基本的内存使用上没有什么限制然而在 Node 中通过 JavaScript 使用内存时就会发现只能使用部分内存64 位系统下约为 1.4GB32 位系统下约为 0.7GB在这样的限制下将会导致 Node 无法直接操作大内存对象
造成这个问题的主要原因在于 Node 基于 V8 构建所以在 Node 中使用的 JavaScript 对象基本上都是通过 V8 自己的方式来进行分配和管理的V8 的这套内存管理机制在浏览器的应用场景下使用起来绰绰有余足以胜任前端页面中的所有需求但在 Node 这却限制了开发者随心所欲使用大内存的想法
## Node 的发展历史
- 2008 年左右随着 Ajax 的逐渐普及Web 开发逐渐走向复杂化系统化
@ -98,59 +130,101 @@ JS 语言非常灵活,使得它在严谨性方面不如 Java 等传统的静
## Node.js 的应用
Node.js 拥有强大的开发者社区现在已经发展出比较成熟的技术体系以及庞大的生态它被广泛地应用在 Web 服务开发工作流客户端应用等诸多领域其中 Web 服务领域业界对 Node.js 的接受程度最高
Node.js 拥有强大的开发者社区现在已经发展出比较成熟的技术体系以及庞大的生态它被广泛地应用在 Web 服务开发工作流客户端应用等诸多领域其中 **Web 服务**领域业界对 Node.js 的接受程度最高
### Node.js 的用途
### 1BFF 中间层
**1中间层**
BFF Backend For Frontend服务于前端的后端玉伯在[从前端技术进化到体验科技](https://mp.weixin.qq.com/s/IYddaaw2ps1wR2VT1dZWPg)》这篇文章中点出了 BFF 层的概念:
前端访问中间层的接口中间层再访问后台的 Java/C++ 服务这类服务的特点是不需要太强的服务器运算能力但对程序的灵活性有较高的要求
> BFF 模式下整体分工很清晰**后端通过 Java/C++ 等语言负责服务实现理想情况下给前端提供的是基于领域模型的 RPC 接口前端则在 BFF 层直接调用服务端 RPC 接口拿到数据**按需加工消费数据并实现人机交互基于 BFF 模式的研发很适合拥有前端技术背景的全栈型工程师这种模式的好处很明显后端可以专注于业务领域更多从领域模型的视角去思考问题页面视角的数据则交给前端型全栈工程师去搞定**领域模型与页面数据是两种思维模式通过 BFF 可以很好地解耦开让彼此更专业高效**
这样做的好处是安全性不会把主服务器暴露在外面提高性能做缓存等降低主服务器的复杂度
Web 服务里搭建一个中间层前端访问中间层的接口中间层再访问后台的 Java/C++ 服务这类服务的特点是不需要太强的服务器运算能力但对程序的灵活性有较高的要求这两个特点正好和 Node.js 的优势相吻合Node.js 非常适合用来做 BFF 优势如下
- 对于前端来说让前端**有能力自由组装后台数据**这样可以减少大量的业务沟通成本加快业务的迭代速度并且前端同学能够**自主决定**与后台的通讯方式
- 对于后台和运维来说好处是安全性不会把主服务器暴露在外面降低主服务器的复杂度等
### 2服务端渲染
**客户端渲染**CSR / Client side render前端通过一大堆接口请求数据然后通过 JS 动态处理和生成页面结构和展示优点是**前后端分离**减小服务器压力局部刷新缺点是不利于 SEO如果你的页面然后通过 Ajax 异步获取内容抓取工具并不会等待异步完成后再行抓取页面内容首屏渲染慢
**服务端渲染**SSR / Server Side Render服务器返回的不是接口数据而是一整个页面或整个楼层 HTML 字符串浏览器直接显示即可也就是说在服务器端直接就渲染好了然后一次性打包返回给前端优点是**有利于 SEO首屏渲染很快**
**总结 搜索引擎优化 + 首屏速度优化 = 服务端渲染**
备注这里的服务端渲染只是让 Node.js 做中间层不会替代后端的后台同学请放心
参考链接
- [Vue 服务端渲染的概念](https://ssr.vuejs.org/zh/)
- <https://blog.csdn.net/u012036171/article/details/88833200>
- <https://juejin.im/post/5c068fd8f265da61524d2abc>
- [方应杭](https://www.zhihu.com/question/59578433/answer/326694511)
历史回顾
1一开始页面很简单html 是后端渲染的比如PHPASPJSP等方式后端发现页面中的 js 好麻烦虽然简单但是坑多于是让公司招聘专门写 js 的人简称前端切图仔
2随着 Node.js 和前端 MVC 的兴起以及前端越来越复杂慢慢演变成了前后端分离
3前端的 SPA 应用流行之后发现 SEO 问题很大而且首屏渲染速度很慢但是自己选的路再难走也要走下去于是用 Node.js 在服务端渲染被看成是一条出路
4以前在一起的时候是后端做部分前端的工作现在在一起的时候是前端做部分后端的工作
### 3做小型服务小型网站的后端基于 ExpressKoa 框架
现在很多公司的后台管理系统都是用 Node.js 来开发接口毕竟后台管理系统对性能和并发的要求不是太高有了 Node.js 之后通过 JS 直接操作 DB做增删改查生成接口极大降低了前端同学的学习门槛
当然有时候做 Node.js 开发是因为后台人力不够所以把后台开发的一部分工作量转移给前端同学
**2做小型服务小型网站的后端**比如后台管理系统
### 4做项目构建工具
现在很多公司的后台管理系统都是用 Node.js来开发接口直接操作 DB
前端正在广泛使用的构建工具 gulpWebpack就是基于 Node.js 来实现的
不过短期来看Node.js 很难像 Java/C++ 那样成为后台的主力开发语言这并非是因为 Node.js 的性能问题实际上Node.js 的性能还不错主要是因为Node.js 还比较年轻框架的支持度不够很难独立成为后台开发语言但未来可期
### 5 PC 端的软件基于 Electron 框架
**3做公司内部工具项目构建工具**
Electron 框架就是基于 Node.js 也可以说Electron Node.js 在PC客户端的技术
有一点你可能会感到惊讶程序员们都在用的代码编辑器 VS Code 软件 就是用 JS 语言实现的
### Node.js 的主要应用领域
- RESTFul API
- 实时通信如消息推送等
- 高并发
- I/O 阻塞
还有一个例子是电子游戏直播网站 [Twitch](https://www.twitch.tv/),号称是国外游戏直播的鼻祖,它在 PC 端的客户端软件,就是用 Electron 框架的。你会发现Twitch 的网站视觉,和 PC 端的视觉,几乎是一样的。如果两端都采用 JS 语言,就可以极大的复用现有的工程。
### 知名度较高的 Node.js 开源项目
![](http://img.smyhvae.com/20180301_2009.png)
- expressNode.js 中著名的 web 服务器框架
- expressNode.js 中著名的 web 服务框架
- Koa下一代的 Node.js Web 框架
- Koa下一代的 Node.js Web 服务框架所谓的下一代是相对于 Express 而言的
- mocha功能强大的 node.js 测试框架
- [Egg](https://eggjs.org/zh-cn/)2016 年,阿里巴巴研发了知名的 Egg.js 开源项目,号称企业级 Web 服务框架。Egg.js 是基于 Koa 开发的。
- PM2node 本来是单进程的PM2 可以实现和管理多进程
* mocha是现在最流行的 JavaScript 测试框架在浏览器和 Node 环境都可以使用
- jade非常优秀的模板引擎不仅限于 js 语言
* PM2node 多进程管理
- CoffeeScript用简洁的方式展示 JavaScript 优秀的部分
* jade非常优秀的模板引擎不仅限于 js 语言
- Atom文本编辑器
* CoffeeScript用简洁的方式展示 JavaScript 优秀的部分
- socket.io实时通信框架
* Atom编辑器
## 前端同学会 Node.js 就真的全栈了吗
* VS Code最酷炫的编辑器
* socket.io实时通信框架
### 总结
或许能用 Node.js 做的后台应用Java/C++ 也能做但是 Node.js 可以让我们多一种选择
短期来看Node.js 很难像 Java/C++ 那样成为后台的主力开发语言这并非是因为 Node.js 的性能问题主要是因为Node.js 还比较年轻经验积累太少框架的支持度不够搞企业级服务Node.js 敌不过 Java/C++所以目前只能搞轻量级但未来可期
限制语言能力的不是语言本身而是生态
## 最后一段前端同学会 Node.js 就真的全栈了吗
一个人的精力是有限的既擅长前端又精通后端的人毕竟是极少数
@ -162,58 +236,7 @@ Node.js 拥有强大的开发者社区,现在已经发展出比较成熟的技
对于个人而言虽然全栈很难但是 Node.js 的出现** JS 语言实现了前后端语法的统一 JS 语言的技术栈更佳全面**
涉及到后台开发相关的技术无论如何也绕不开**框架设计开发调试数据库操作高并发处理大规模存储性能优化容灾方案操作系统调度甚至是 Linux 内核驱动开发**等过硬的知识技能和经验积累等你亲身经历过这些才算明白语言只是一种工具
## V8 引擎
### 运行环境平台的含义
首先JavaScript 语言通过 Node 在服务器上运行在这个意义上Node.js 的地位相当于 JavaScript 在服务器端的虚拟机类似于 Java 语言中的 Java 虚拟机
其次Node 生态系统活跃提供了大量的开源库使得 JavaScript 语言能与操作系统进行交互在这个层次上Node 又是属于 JavaScript 的工具库
**补充**
PHPJSPPythonPerlRuby 既是语言也是平台不同Node.js 的使用 JavaScript 进行编程运行在 Chrome V8 引擎上
PHPJSP 等相比PHPJSP.net 都需要运行在服务器程序上ApacheNginxTomcatIIS
Node.js 跳过了 ApacheNaginxIIS HTTP 服务器它自己不用建设在任何服务器软件之上Node.js 的许多设计理念与经典架构LAMP = Linux + Apache + MySQL + PHP有着很大的不同可以提供强大的伸缩能力Node.js 没有 web 容器
### V8 Node
Chrome 浏览器成功的背后离不开 JS V8 引擎作为虚拟机V8 的性能表现优异它的开发者是 Lars Bak Lars 的工作履历里绝大部分都是与虚拟机相关的工作在开发 V8 之前他曾经在 Sun 公司工作担任 HotSpot 团队的技术领导主要致力于开发高性能的 Java 虚拟机在这之前他也曾为 SelfSmalltalk 语言开发过高性能虚拟机这些无与伦比的经历让 V8 一出世就超越了当时所有的 JS 虚拟机
![](http://img.smyhvae.com/20200617_1120.png)
V8 的性能优势使得用 JavaScript 写高性能后台服务程序成为可能在这样的契机下Ryan Dahl 选择了 JavaScript选择了 V8在事件驱动非阻塞 I/O 模型的设计下实现了 Node
### V8 的内存限制
在一般的后端开发语言中在基本的内存使用上没有什么限制然而在 Node 中通过 JavaScript 使用内存时就会发现只能使用部分内存64 位系统下约为 1.4GB32 位系统下约为 0.7GB在这样的限制下将会导致 Node 无法直接操作大内存对象
造成这个问题的主要原因在于 Node 基于 V8 构建所以在 Node 中使用的 JavaScript 对象基本上都是通过 V8 自己的方式来进行分配和管理的V8 的这套内存管理机制在浏览器的应用场景下使用起来绰绰有余足以胜任前端页面中的所有需求但在 Node 这却限制了开发者随心所欲使用大内存的想法
## Node.js 的特点
- 异步非阻塞 IO 模型
- 事件循环
- 单线程
- 总结轻量和高效
Node.js 的性能和效率非常高
传统的 Java 语言是一个请求开启一个线程当请求处理完毕后就关闭这个线程 Node.js 则完全没有采用这种模型它本质上就是一个单线程
你可能会疑问一个线程如何服务于大量的请求如何处理高并发的呢这是因为Node.js 采用的是异步的非阻塞的模型
这里所谓的单线程指的是 Node 的主线程只有一个为了确保主线程不被阻塞主线程是用于接收客户端请求但不会处理具体的任务 Node 的背后还有一个线程池线程池会处理长时间运行的任务比如 IO 操作网络操作线程池里的任务是通过队列和事件循环的机制来执行
## SSR 服务端渲染
提高搜索引擎抓取网页的
涉及到后台开发相关的技术无论如何也绕不开**框架设计开发调试数据库操作高并发处理大规模存储性能优化容灾方案RPC 调用进程管理操作系统调度网络安全系统运维日常维护甚至是 Linux 内核驱动开发**等过硬的知识技能和经验积累等你亲身经历过这些才算明白语言只是一种工具
## 我的公众号

View File

@ -1,5 +1,24 @@
### 使用 Node.js 时的劣势
## Node.js 的特点
- 异步非阻塞 IO 模型
- 事件循环
- 单线程
- 总结轻量和高效
Node.js 的性能和效率非常高
传统的 Java 语言是一个请求开启一个线程当请求处理完毕后就关闭这个线程 Node.js 则完全没有采用这种模型它本质上就是一个单线程
你可能会疑问一个线程如何服务于大量的请求如何处理高并发的呢这是因为Node.js 采用的是异步的非阻塞的模型
这里所谓的单线程指的是 Node 的主线程只有一个为了确保主线程不被阻塞主线程是用于接收客户端请求但不会处理具体的任务 Node 的背后还有一个线程池线程池会处理长时间运行的任务比如 IO 操作网络操作线程池里的任务是通过队列和事件循环的机制来执行
## 使用 Node.js 时的劣势
- 程序运行不稳定可能会出现服务不可用的情况

View File

@ -1,10 +1,13 @@
## Node.js API文档
## Node.js 官方API文档
Node.js 的API文档英文 <https://nodejs.org/docs/latest-v8.x/api/index.html>
Node.js 的API文档中文<http://nodejs.cn/api/>
- Node.js 的API文档英文 <https://nodejs.org/docs/latest-v8.x/api/index.html>
- Node.js 的API文档中文<http://nodejs.cn/api/>
关于 Node.js 的内置模块和常见API可以看官方文档
查阅文档时稳定指数如下
@ -41,6 +44,39 @@ console.log(path.resolve('../'));
require方法用于加载模块
常见的内置模块包括
- FS文件系统模块
- path路径模块
- OS操作系统相关
- net网络相关
- http
- ...
你可能会有疑问Node.js 这么牛吗还能直接和操作系统做交互
带着这个疑问我们不妨简单看看 Node.js 的源码 os 模块举例
- 打开os模块的源码<https://github.com/nodejs/node/blob/master/lib/os.js>,翻到最底部,找到 `cpus`这个方法
- 进而找到 `getCPUs()`
- internalBinding('os')通过 internalBinding 可以调用系统底层的方法internalBinding 主要是 JS 虚拟机在做的事情
- `internalBinding('os')` 的实现 <https://github.com/nodejs/node/blob/master/src/node_os.cc> 里,里面都是 C++ 的代码。比如有一个`getCPUs`方法。
现在你知道了JS本身是没有能力获取底层系统资源的这一切都是 JS虚拟机在和底层做交互然后通过 JS 的表现形式暴露给应用层
另外还有很多库是直接使用C/++编写的通过编译之后再提供给 JS 应用层调用或者直接提供给 Node.js层使用
**所有的编程语言底层都会回归C/C++**甚至是汇编语言
### 2require 加载第三方包的机制
```js