--- title: 01-Node.js介绍 publish: true --- ## todo - rpc 和 Node.js 的关系 - [《吊打面试官》系列 Node.js 全栈秒杀系统](https://mp.weixin.qq.com/s/uWeAsJ-P253je15A49uKIQ) ## 前言 Node 的重要性已经不言而喻,很多互联网公司都已经有大量的高性能系统运行在 Node 之上。Node 凭借其单线程、异步等举措实现了极高的性能基准。此外,目前最为流行的 Web 开发模式是前后端分离的形式,即前端开发者与后端开发者在自己喜欢的 IDE 上独立进行开发,然后通过 HTTP 或是 RPC 等方式实现数据与流程的交互。这种开发模式在 Node 的强大功能的引领下变得越来越高效,也越来越受到各个互联网公司的青睐。 ### 前端同学为什么要学习后端/后端同学为什么要学习前端 - 了解前后端交互流程。 - 前端同学能够和后台开发的程序员更佳紧密地结合、更顺畅地沟通。 - 当网站的业务逻辑需要前置时,前端人员需要学习一些后台开发的技术,以完成相应的任务;;反过来也一样。 - 拓宽知识视野和技术栈,能够站在全局的角度审视整个项目。 ### 前端同学为什么要学 Node.js 1、Node.js 使用 JavaScript 语言开发服务器端应用,**便于前端同学上手**(一些公司甚至要求前端工程师掌握 Node.js 开发)。 2、实现了前后端的语法统一,**有利于和前端代码整合**,甚至共用部分代码。 比如说,针对接口返回的各种字段,前后端都必须要做校验。此时,如果用 Node.js 来做后台开发的话,前后端可以共用校验的代码。 3、Node.js 性能高、生态系统活跃,提供了大量的开源库。 4、Jeff Atwood 在 2007 年提出了著名的 Atwood 定律:**任何能够用 JavaScript 实现的应用系统,最终都必将用 JavaScript 实现**。 Jeff Atwood 是谁不重要(他是 Stack Overflow 网站的联合创始人),重要的是这条定律。 ### 后端同学为什么要学 Node.js 因为前端同学在学 Node.js。 ## 什么是 Node.js ### 官方定义 [Node.js](https://nodejs.org/zh-cn/) 是一个基于 **Chrome V8 引擎**的 JavaScript 运行环境。Node.js 使用了一个**事件驱动**、**非阻塞式 I/O**的模型,使其轻量又高效。Node.js 的包管理工具 npm 是全球最大的开源库生态系统。 Node.js 不是一门语言,也不是 JavaScript 的框架,也不是像Nginx一样的Web服务器 ,**Node.js 是 JavaScript 在服务器端的运行环境(平台)**。 ### 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:标签元素相关的API - BOM:浏览器相关的API ECMAScript 是 JS 的语法;DOM 和 BOM 浏览器端为 JS 提供的 API。 而 Node.js 的组成分为: - **ECMAScript**。ECMAScript 的所有语法在 Node 环境中都可以使用。 - **Node 环境**提供的一些**附加 API**(包括文件、网络等相关的 API)。 如下图所示: ![](http://img.smyhvae.com/20200409_1545.png) ### 补充 与 PHP、JSP、Python、Perl、Ruby 的“既是语言,也是平台”不同,Node.js 的使用 JavaScript 进行编程,运行在 Chrome 的 V8 引擎上。 与 PHP、JSP 等相比(PHP、JSP、.net 都需要运行在服务器程序上,Apache、Nginx、Tomcat、IIS。 ),Node.js 跳过了 Apache、Naginx、IIS 等 HTTP 服务器,它自己不用建设在任何服务器软件之上。Node.js 的许多设计理念与经典架构(LAMP = Linux + Apache + MySQL + PHP)有着很大的不同,可以提供强大的伸缩能力。Node.js 没有 web 容器。 JS 语言非常灵活,使得它在严谨性方面不如 Java 等传统的静态语言。JS 是一门动态语言,而且融合了面向对象和函数式编程这两种编程范式。 随着 ES6、ES7 等 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 虚拟机。在这之前,他也曾为 Self、Smalltalk 语言开发过高性能虚拟机。这些无与伦比的经历让 V8 一出世就超越了当时所有的 JS 虚拟机。 ![](http://img.smyhvae.com/20200617_1120.png) V8 的性能优势使得用 JavaScript 写高性能后台服务程序成为可能。在这样的契机下,Ryan Dahl 选择了 JavaScript,选择了 V8,在事件驱动、非阻塞 I/O 模型的设计下实现了 Node。 ### V8 的内存限制 在一般的后端开发语言中,在基本的内存使用上没有什么限制,然而在 Node 中通过 JavaScript 使用内存时就会发现只能使用部分内存(64 位系统下约为 1.4GB,32 位系统下约为 0.7GB)。在这样的限制下,将会导致 Node 无法直接操作大内存对象。 造成这个问题的主要原因在于 Node 基于 V8 构建,所以在 Node 中使用的 JavaScript 对象基本上都是通过 V8 自己的方式来进行分配和管理的。V8 的这套内存管理机制在浏览器的应用场景下使用起来绰绰有余,足以胜任前端页面中的所有需求。但在 Node 中,这却限制了开发者随心所欲使用大内存的想法。 ## Node 的发展历史 - 2008 年左右,随着 Ajax 的逐渐普及,Web 开发逐渐走向复杂化,系统化; - Node.js 诞生于 2009 年,由 Joyent 的员工 Ryan Dahl 开发而成。2009 年 5 月,Ryan Dahl 在 GitHub 中开源了 Node 的最初版本,同年 11 月,在 JSConf 大会上展示了 Node 项目; - 2010 年 1 月,NPM 包管理工具诞生,使得程序员能够更方便地发布和分享 Node.js 的第三方库。 - Node.js 最初只支持 Linux 和 Mac OS 操作系统。2011 年 7 月,微软参与合作,Node.js 终于支持了 Windows 平台。PS:不过,node 的生产环境基本是在 Linux 下。 - 目前官网最新版本已经更新到 14.x.x 版本,最新稳定的是 12.18.0。 据 Node.js 创始人 Ryan Dahl 回忆,他最初希望采用 Ruby,但是 Ruby 的虚拟机效率不行。 注意:是 Node 选择了 JavaScript,不是 JavaScript 发展出来了一个 Node。 ## Node.js 的应用 Node.js 拥有强大的开发者社区,现在已经发展出比较成熟的技术体系,以及庞大的生态。它被广泛地应用在 Web 服务、开发工作流、客户端应用等诸多领域。其中,在 **Web 服务**领域,业界对 Node.js 的接受程度最高。 ### 1、BFF 中间层 BFF,即 Backend For Frontend(服务于前端的后端)。玉伯在《[从前端技术进化到体验科技](https://mp.weixin.qq.com/s/IYddaaw2ps1wR2VT1dZWPg)》这篇文章中点出了 BFF 层的概念: > 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://www.zhihu.com/question/59578433/answer/326694511) 历史回顾: (1)一开始,页面很简单,html 是后端渲染的(比如PHP、ASP、JSP等方式)。后端发现页面中的 js 好麻烦(虽然简单,但是坑多),于是让公司招聘专门写 js 的人,简称「前端切图仔」。 (2)随着 Node.js 和前端 MVC 的兴起,以及前端越来越复杂,慢慢演变成了「前后端分离」。 (3)前端的 SPA 应用流行之后,发现 SEO 问题很大,而且首屏渲染速度很慢,但是自己选的路再难走也要走下去,于是用 Node.js 在服务端渲染被看成是一条出路。 (4)以前在一起的时候,是后端做部分前端的工作;现在在一起的时候,是前端做部分后端的工作。 ### 3、做小型服务、小型网站的后端(基于 Express、Koa 框架) 现在很多公司的后台管理系统,都是用 Node.js 来开发接口,毕竟,后台管理系统对性能和并发的要求不是太高。有了 Node.js 之后,通过 JS 直接操作 DB,做增删改查,生成接口,极大降低了前端同学的学习门槛。 当然,有时候做 Node.js 开发,是因为:后台人力不够,所以把后台开发的一部分工作量,转移给前端同学。 ### 4、做项目构建工具 前端正在广泛使用的构建工具 gulp、Webpack,就是基于 Node.js 来实现的。 ### 5、 做 PC 端的软件(基于 Electron 框架) Electron 框架就是基于 Node.js 的。也可以说:Electron 是 Node.js 在PC客户端的技术。 有一点你可能会感到惊讶:程序员们都在用的代码编辑器 VS Code 软件, 就是用 JS 语言实现的。 还有一个例子是:电子游戏直播网站 [Twitch](https://www.twitch.tv/),号称是国外游戏直播的鼻祖,它在 PC 端的客户端软件,就是用 Electron 框架的。你会发现,Twitch 的网站视觉,和 PC 端的视觉,几乎是一样的。如果两端都采用 JS 语言,就可以极大的复用现有的工程。 ### 知名度较高的 Node.js 开源项目 ![](http://img.smyhvae.com/20180301_2009.png) - express:Node.js 中著名的 web 服务框架。 - Koa:下一代的 Node.js 的 Web 服务框架。所谓的“下一代”是相对于 Express 而言的。 - [Egg](https://eggjs.org/zh-cn/):2016 年,阿里巴巴研发了知名的 Egg.js 开源项目,号称企业级 Web 服务框架。Egg.js 是基于 Koa 开发的。 * mocha:是现在最流行的 JavaScript 测试框架,在浏览器和 Node 环境都可以使用。 * PM2:node 多进程管理。 * jade:非常优秀的模板引擎,不仅限于 js 语言。 * CoffeeScript:用简洁的方式展示 JavaScript 优秀的部分。 * Atom:编辑器。 * VS Code:最酷炫的编辑器。 * socket.io:实时通信框架。 ### 总结 或许,能用 Node.js 做的后台应用,Java/C++ 也能做;但是 Node.js 可以让我们多一种选择。 短期来看,Node.js 很难像 Java/C++ 那样,成为后台的主力开发语言。这并非是因为 Node.js 的性能问题,主要是因为,Node.js 还比较年轻,经验积累太少,框架的支持度不够。搞企业级服务,Node.js 敌不过 Java/C++,所以目前只能搞「轻量级」;但未来可期。 限制语言能力的不是语言本身,而是生态。 ## 最后一段:前端同学会 Node.js 就真的全栈了吗? 一个人的精力是有限的,既擅长前端、又精通后端的人,毕竟是极少数。 林肯说过:“你可以在所有的时间欺骗一部分人,也可以在一段时间欺骗所有的人,但你不可能在所有的时间欺骗所有的人”。 同样的,我也说过:“你可以在这一段时间擅长前端技术,也可以在另一段时间擅长后台技术,但你不可能在**同一段时间**同时擅长前端和后台,更不可能在**所有的时间**同时擅长前端和后台。” 所谓的全栈,只是一个伪命题。个人不一定需要全栈,企业和项目也不强制要求全栈,分工协作,才最高效。 对于个人而言,虽然全栈很难,但是 Node.js 的出现,**让 JS 语言实现了前后端语法的统一,让 JS 语言的技术栈更佳全面**。 涉及到后台开发相关的技术,无论如何,也绕不开**框架设计、开发调试、数据库操作、高并发处理、大规模存储、性能优化、容灾方案、RPC 调用、进程管理、操作系统调度、网络安全、系统运维、日常维护、甚至是 Linux 内核、驱动开发**等过硬的知识技能和经验积累。等你亲身经历过这些,才算明白:语言只是一种工具。 ## 我的公众号 想学习**更多技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: ![](https://img.smyhvae.com/20200102.png) ##