笔者自今年的下半年也就是八九月的时候从PHP转到了Node.js,因为Node.js不管是前端还是全栈真地位都很重要,尤其前端,还有js全栈。但是笔者本人学的杂,没花太多时间去系统化的进行一个学习,也没有一个完整的学习思路。每次自己要做点什么东西的时候都要到处查,而且很堵,代码优化也是稀烂。准备重新学习和整理Node.js的一些体系,然后把自己学习的总结发出来,大佬们如果觉得有写的不对的可以发评论区指教指教。
学习Node.js之前得先了解基本的JavaScript知识。

Node.js是什么?

Node.js的logo

这个。。。官网给的简介是:

Node.js® 是一个免费、开源、跨平台的 JavaScript 运行时环境,它让开发人员能够创建服务器、Web 应用、命令行工具和脚本。

准确来说,Node.js不是一个新的编程语言也不是一个JavaScript框架,而是是一个JavaScript运行时,用来支持JavaScript运行,类比C/C++的GUN编译器。

先用一个类比的示例来进行解释。比如,有人向你发送了一个扩展名为docx的文档,你想要查看其中的内容,于是打开记事本,把该文档拖到记事本的窗口里,然后就看到了一大堆乱码。这是因为记事本程序并不能识别这种格式的文档,你需要先安装Microsoft Office 2007以上版本的软件,然后用Word程序打开,这样才能看到正确解码的内容。

如果把示例中的docx文件看作程序,那么Word就是它的运行环境,这就像JavaScript程序与浏览器的关系一样。如果你了解过现代浏览器的结构,就会知道其中包含了JavaScript引擎。

以前,想要查看docx文件的内容,几乎只能依赖于Microsoft Office,后来金山公司也推出了办公软件工具WPS Office,它也能够解释和运行docx文件,于是docx文件就有了多个可运行环境,而Node.js对于JavaScript语言的意义也是如此。

为了更加直观地理解运行时的概念,你可以尝试一个有趣的实验,自己创造一种简单的编程语言,规定一些简易的语法,然后使用JavaScript来编写能够解释这些语法的代码。

例如,用自创的语言编写一些简单的程序,最后通过Node.js运行JavaScript程序,并在程序中用Node.js提供的文件读写接口(File API)读入你用自创的编程语言编写的程序,看看它能否被正确地解释和执行。待你了解了JavaScript是如何完成对自创编程语言的解释和执行的,自然就能明白在Node.js运行环境中,C/C++对JavaScript脚本做了什么事情。

当然,真实的代码解释执行过程要复杂得多,很多关键的思想和技术也被应用在前端框架的设计中,这些可以在今后的学习中慢慢消化。

理解运行时

上面提到了 Node.js 给 JavaScript 提供了一个运行环境,提供这个运行环境是用来做啥呢?
我们都知道浏览器本身也给 JavaScript 提供了一个运行环境,在这个环境中,JS 可以调用浏览器提供的一些 API ,来调用浏览器的一些功能,比如 DOM 操作、window 对象、如定时器等等,这些 API 都是浏览器的 JavaScript 运行时环境提供的,而在 chrome 浏览器,这个运行时环境是 Chromium,它会通过执行引擎 V8 在 JavaScript 执行过程中注入这些 API(运行时环境Chromium和执行引擎V8是从趣学 Node.js中看到的这个说法,查询到的其他资料很少会明确指出)。

关系图

注意,V8引擎会解析和运行choromium提供的api
扩展一下就是:JavaScript 运行时 指的是提供给 API 给 JavaScript 来调用外界程序功能的运行环境。
Node.js 也是使用 V8 引擎 进行解析和执行 JavaScript ,然后给其注入其指定的 API ,然后提供 JavaScript 运行的环境,在这个环境中, JavaScript 就可以通过 V8引擎 调用 Node.js 运行时环境 提供的 API 来调用服务器的一些功能,比如文件读取、网络请求等功能。

如何安装Node.js

安装其实很简单,直接去https://nodejs.org/download/ 下载即可。

Ubuntu系统下可以使用:

apt install nodejs

还有npm包管理器

apt install npm

NPM包管理器

npm是Node.js的标准包管理器。

据报道,2022年9月,npm注册表中列出了超过210万个软件包,使其成为地球上最大的单一语言代码库,你可以肯定有一个软件包(几乎!)一切.

它最初是一种下载和管理Node.js包的依赖关系的方法,但后来它也成为前端JavaScript中使用的工具。

npm安装,更新和管理项目依赖项的下载。冗余是预构建的代码片段,例如库和包,您的Node.js应用程序需要这些代码片段。

一次性安装项目依赖

如果一个项目有一个package.json文件

npm install

它将在node_modules文件夹中安装项目所需的所有内容,如果它还不存在,则创建它。

Installing a single package安装单个软件包

npm install <package-name>

这样即可

此外,从npm 5开始,此命令将添加到package.json文件依赖项中。在版本5之前,你需要添加参数--save。

通常你会看到更多的参数添加到这个命令:

  • --save-dev安装并将条目添加到package.json文件devendencies中
  • --no-save安装但不将条目添加到package.json文件依赖项
  • --save-optional安装并将条目添加到package.json文件的optionalconfigurations
  • --no-optional将阻止安装可选依赖项

其他的也不好多说。

Node.js能干什么

创建高性能Web服务器
许多Node.js的初学者应该都见过那段只用了不到10行代码就建立了一个Web服务器的经典示例。尽管对于前端开发人员而言,他们依然需要学习基本的Web服务器知识,才能更加得心应手地进行服务端开发,但与配置Apache或Nginx来实现同样的功能相比,这样的学习成本已经非常低了,毕竟前端开发人员可以使用自己最熟悉的JavaScript语言来构建应用。

另一方面,在Node.js中,代码可以与各类数据库进行交互,这就意味着前端工程师可以直接使用JavaScript语言编写与数据库进行交互的代码(尽管在大型应用中并不推荐这样做),且编写业务逻辑代码时,Node.js与其他后端语言没有明显的差别,因此前端开发人员不用切换开发语言就可以掌握全栈开发的技能。

由于Node.js底层使用的是异步非阻塞的I/O机制,因此它更适合于I/O密集、少量业务逻辑和计算消耗的场景。尽管解释型脚本语言本身并不适合执行计算型任务,但Node.js底层是由C/C++代码编写的,并且提供了JavaScript代码层与C/C++代码交互的接口,面对计算密集型任务时,Node.js只需要作为启动脚本调用底层C/C++程序来完成计算密集型任务就可以了。

服务端执行的任务大体可分为读写密集型任务和计算密集型任务。对于读写密集型任务而言,CPU更多的时间是在等待磁盘读写,使用率并不高,在Web服务器上进行的网络通信、信息传输和磁盘读写等都属于读写操作,它对磁盘的响应速度和传输效率有着更高的需求。

相较而言,计算密集型任务对CPU的运算能力要求更高,但对磁盘读写造成的性能负担很小,计算过程中通常也不需要与I/O接口进行交互,可直接、高效地在内存中执行,这类任务的计算过程通常比较复杂,例如需要实现某些加密算法或者矩阵计算等。

大型架构的后端技术选型需要考虑的因素更为复杂,Node.js设计之初并没有准备承担这项任务,就连Node.js之父Ryan Dhal自己也说,在面对大型服务端应用开发时,Node.js的开发体验不如Go语言。

但是,全世界目前有600多种编程语言,没有任何一种语言能够解决所有问题,语言只是承载和传递程序设计思想的媒介,如何为目标场景选择一项合适的技术,或许是开发人员更应该关注的问题。

当你在前端领域有一定的积累时,很多前辈都会推荐你继续学习Java或C++等更为完备也更为复杂的语言,这样做的目的并不仅仅是扩展能力边界,更多的是希望你能够跳出一种编程语言的束缚,学习和体会编程语言背后的思想。

笔者知道的Node.js只能用来干这个了。。。

招黑的JavaScript工程师

Node.js凭借创建高性能Web服务器以及与数据库通信的能力,为前端开发人员提供了服务端开发的机会。早在几年之前,开发人员就可以使用MEAN(MongoDB + Express + Angular.js + Node.js)这种纯JavaScript技术栈完成闭环的业务逻辑开发,很多前端工程师也因此自诩为全栈工程师。

不可否认当年这样的技术栈确实可以使许多中小型团队以更少的人力和时间就把产品从创意阶段推进到线上,但这也使得JavaScript开发人员成为业内最招黑的全栈工程师,因为业务逻辑的实现并不足以撑起全栈工程师进行后端开发。

在企业级开发中,后端开发仍然以Java工程师为主力军。

由于Java本身具有强类型和完整的面向对象的特性,因此后端工程师的编码质量和程序设计意识整体要高于前端工程师,再加上与Java开发体验非常相似的Angular技术栈的支持(Angular本身就是一项由Google的Java工程师开发和维护的技术),后端工程师很容易就能编写出规范性和可维护性都不输于前端开发人员的代码,这大大提升了Java全栈工程师的竞争力。

如果不是工程化配置和CSS实战经验形成的门槛,前端工程师在面对后端全栈工程师时很难体现其自身价值。然而,前端开发出身的工程师在使用Node.js技术栈进行服务端开发时却没有那么顺利,最流行的Express和Koa框架,仅仅提供了框架和基本中间件,要想实现更多的功能,还需要引入或者自行开发大量中间件。

这时开发人员之间的差别就会表现得非常明显,即使完全不懂Node.js,后端开发人员也很清楚自己应该寻找具备日志记录、错误追踪、会话管理、安全校验、性能监控、对象关系映射(ORM)、数据库连接等功能的模块或中间件,而普通的前端开发人员却除了业务逻辑的增删改查外,往往连使用“try...catch...”语句捕获运行时错误的意识都没有。

前端工程师很容易只考虑业务逻辑一切正常的情况,只要主流程能够正常运行,就觉得万事大吉了,然而在真实的开发过程中,往往是那些没有覆盖到的边界情况需要花费更多的精力。

把后端开发等同于编写业务逻辑代码,就好像把前端开发等同于编写静态页面代码一样。如果真的想成为全栈工程师,需要用一颗谦虚求知的心,踏踏实实地去学习那些陌生的知识,学习的过程可能充满艰辛,但你一定会受益于所学的结果。

几段代码:

创建一个HTTP服务器

import { createServer } from 'node:http';

const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World!\n');
});

server.listen(3000, '127.0.0.1', () => {
console.log('Listening on 127.0.0.1:3000');
});

写入测试

import assert from 'node:assert';
import test from 'node:test';

test('that 1 is equal 1', () => {
  assert.strictEqual(1, 1);
});

test('that throws as 1 is not equal 2', () => {
  assert.strictEqual(1, 2);
});

总结

菜鸟教程 上对 Node.js 的定义:

  • Node.js 就是运行在服务端的 JavaScript。
  • Node.js 是一个基于 Chrome JavaScript 运行时 建立的一个平台。
  • Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎 ,V8 引擎 执行 Javascript 的速度非常快,性能非常好。

笔者觉得从不同角度来看也可以这样定义。

  • 第 1 点,可以用于区分它和浏览器端运行的 JavaScript。
  • 第 2 点,可以说明它是一个应用程序,用于支持 JavaScript 运行时建立的一个应用程序。因为 Node.js 本身也是一个开源软件,它在服务器上的安装提供了 Node 程序,该程序本身可以使 JavaScript 文件在该服务器上执行。
  • 第 3 点,就是简单描述 Node.js,和官方的定义最接近。

标签:Node.js, JavaScript

自五月以来使用简幻欢的感受

1 条评论

  1. awa

你的评论