Node 究竟是什么?

以下是你需要了解的关于 Node.js(或简称为 Node)以及它与 npm 的关系

  • Node 是 JavaScript,但它是一种服务器端语言。
  • 这得益于 V8,它是 Chromium 的 JavaScript 引擎,可以在浏览器之外独立运行。
  • Node 和基于浏览器的 JavaScript 可能存在很大差异,并且具有不同的功能,尽管它们的核心都是 JavaScript。
  • 你不需要了解 Node 就可以使用 npm。

你可能已经知道,npm 代表 **Node 包管理器**(即使官方的 npm 网站 在每次页面加载时在其页眉中显示有趣的选择性名称,比如“忍者南瓜变种人”。)

你需要立即理解的关键是:“Node”和“包管理器”是两个独立的重要组成部分,它们共同组成了 npm。

我们将在本 npm 指南的下一章中介绍包管理器的概念以及为什么要考虑使用它。不过现在,让我们先来了解 Node 是什么,因为它理解现代 Web 开发的关键部分。

指南章节

  1. 本指南适用于谁?
  2. “npm”究竟代表什么?
  3. 命令行究竟是什么?
  4. Node 究竟是什么? (您当前位置!)
  5. 包管理器究竟是什么?
  6. 如何安装 npm?
  7. 如何安装 npm 包?
  8. npm 命令究竟是什么?
  9. 如何安装现有的 npm 项目?

Node 是 JavaScript,但它没有浏览器的全部功能

你可能主要将 JavaScript 视为一种在浏览器中运行的语言,类似于 HTML 和 CSS。是的,这些语言都有抽象和超集(例如 HAML 用于 HTML,Sass 用于 CSS,TypeScript 用于 JavaScript,仅举几例),以及编译器和转译器,以及各种将它们转换为这种形状或那种形状的工具。但最终,这些工具生成的都是标准的(即纯)代码,以正确的语法,就像从未使用过抽象一样,在浏览器中运行,并且只能在浏览器中运行。

这件让我理解最长时间的事情,坦白地说,这可能比整个 npm 的事情更像是一个漏掉的消息。JavaScript 不再需要浏览器才能运行。因此,有时我会提到 Node JavaScript,以区分它和“基于浏览器的”JavaScript。

服务器端与客户端语言

在这一点上,我觉得有必要花点时间探讨一下客户端语言(HTML、CSS、JavaScript)和服务器端语言(基本上是所有其他语言)之间的区别。我不会假设你对服务器端语言(如 PHP、Ruby 或 Python)有任何经验,但如果你对服务器端语言的概念完全陌生,你可能需要 了解一下它们是什么。(概括地说:它们是在服务器而不是浏览器上运行的代码语言,通常具有更广泛和更强大的功能。)

这与几年前,大约在 2009 年,一些非常聪明的人非常喜欢 JavaScript 有关。特别是,他们喜欢 JavaScript 的速度(尤其是与当时主要的服务器端语言相比,最突出的是 PHP 和 Ruby),他们希望 JavaScript无处不在,而不仅仅是在浏览器中。

Ryan Dahl 是他们中最杰出的代表人物,他被认为是 Node 的发明者(以及最近的 Deno,它是 Node 的字母重排)。这是一个有趣的事实,但与本主题无关。

Node 的工作原理

不过,真正重要的是,Node 本质上是作为服务器端语言运行的 JavaScript,它浏览器之外运行

这怎么可能呢?从本质上讲,每个浏览器都有自己的 JavaScript 引擎。这是浏览器实际运行 JavaScript 的部分。是的,这显然是浏览器的一个独立部分,而不是 HTML 和 CSS 所用的相同部分——我想当你想到我们在文档和 JavaScript 之间有文字 API 时,这就有道理了。甚至 DOM 的概念 也是这样,当你想到处理 JavaScript 的部门就像 HTML 部门走廊里的一个临时办公室一样,就更有意义了。

基于 Chromium 的浏览器的 JavaScript 引擎被称为 V8,可能是以 一种特定类型的汽车发动机(而不是“蔬菜饮料”,主要由番茄汁制成)命名的。V8 是迄今为止最流行的 JavaScript 引擎。得益于 ECMAScript 在过去大约 15 年中的标准化工作,就浏览器而言,JavaScript 引擎之间实际上没有任何重大差异。Chrome 中使用的引擎与 Firefox 中使用的引擎很像,与 Safari 中使用的引擎也很像,等等。V8 的流行程度现在更多地与 Chrome 的自成体系的普及有关,而不是它与其他引擎之间的区别。

(旁注:Firefox 的 JavaScript 引擎名为 SpiderMonkey。这并不特别相关,但它确实进一步证明了 Firefox 是最酷的。)

为什么这很重要呢?事实证明,你可以将 JavaScript 引擎浏览器中取出,并经过一些修改,让它独立运行——就像你决定把汽车的音响系统从车里拆下来,稍微修理一下,然后把它变成家里的音响系统一样。V8(以及据推测,汽车的音响系统)可以完美地作为任何环境中的独立单元正常运行。

换句话说:V8 使 JavaScript 能够在任何地方运行。这就是为什么我们有“Node”JavaScript 和“基于浏览器的”JavaScript。

Node 几乎(但不完全)是 JavaScript

回顾一下:JavaScript 现在是一种服务器端语言!它被称为 Node,这意味着你可能甚至不需要学习任何其他服务器端语言。我们都是前端开发人员,而且 我们现在拥有超能力

然而,尽管如此,Node 和你在浏览器中运行的 JavaScript 既相似又非常不同。

冒着陷入过多细节的风险:虽然它们的核心都是 JavaScript,并且语言和语法相同,但浏览器中 JavaScript 的许多主要部分(如 windowdocument,甚至是经常被认为理所当然的 alert)在纯粹的服务器端 Node 环境中不存在。当然,当语言只是在独立运行而不是在浏览器中运行时,就没有窗口了。初学者往往会惊讶地发现,即使是 fetch 实际上也是浏览器 API,而不是“纯”JavaScript。

不过,不用担心。console.log 仍然是你最好的朋友,Node JavaScript 有很多的特定于环境的功能,与浏览器对 JavaScript 的实现不同,例如 process 对象,它包含有关当前正在运行的所有进程的详细信息。

多年来,Node 及其生态系统经常出于必要性而朝与基于浏览器的 JavaScript 完全不同的方向发展。(举一个明显的例子:这两种 JavaScript 之间的导入语法多年来一直不同,直到现在才开始重新合并。我们将在 最后一章 中详细介绍。)

在获取新功能方面,Node 长期以来一直享有比浏览器快得多的优势,并且也需要应对自己的一系列问题。它开始像 Ruby 和 PHP 多年来所做的那样为服务器端应用程序提供动力,即使浏览器仍在努力在标准方面达成一致。这导致 Node JavaScript 和基于浏览器的 JavaScript 变得越来越像表兄弟而不是克隆。

我认为,为了解释这两种 JavaScript 表兄弟之间的差异,可以做一个恰当的类比:可以想象两种相似的乐器,比如低音提琴和现代电贝斯。两种乐器都是按相同的音调调音的,演奏相同的音符;如果你懂一种,在很多方面,你也可以说懂另一种。但是,虽然你学习一种乐器后学习另一种会容易很多,但演奏新的乐器与你习惯的方式将会非常不同。

相同,但不同(照片来源:Wikimedia CommonsUnplash

同样,虽然一个开发人员可能编写一种类型的 JavaScript,而另一个开发人员编写另一种类型的 JavaScript,但他们的工作不太可能相同。

Node 是 JavaScript,具有前面提到的其他服务器端语言的功能——比如读取和写入文件系统、访问系统级 API、电子邮件、监听和响应请求、计划任务……等等。

我在这里不再多说,但请记住,尽管它们最终都是 JavaScript,但它们在不同的环境中运行,并且每个环境都能做一些另一个环境无法做到的事情。即使您以前编写过基于浏览器的 JavaScript,Node 仍然可能让您感到有点陌生,因为它超出了基本语法,并且经常以截然不同的方式使用。

在本地运行 Node

与服务器端语言通常一样,您 *确实* 需要在使用 Node 之前安装它。

Node 通常与 npm 一起安装,作为一个整体,因为包管理器部分需要 Node,而 Node 部分在使用包管理器时更有用。(你可以说它们是一笔 *打包* 的交易。不,我不会为这个笑话道歉。毕竟我是一个爸爸。)

我想强调的是,**你不需要了解 Node 就能使用 npm**。因此,即使我将在下面介绍一些 Node 示例,请将本节内容视为一些不错的了解内容,但对于 npm 来说并不是必要的。我觉得,为了更全面地了解 Node 的工作原理,还是有必要稍微了解一下 Node 的工作原理。

我们将在本指南的下一章中介绍 如何安装 Node 和 npm。因此,如果您还没有安装,您可以跳过这一部分,或者在准备好后再来这里。无论哪种方式,这对于跟随本 npm 指南都无关紧要。

如果您想试用一下,可以创建一个新的 test.js 文件,并在其中放入一些通用的 JavaScript 代码。以下代码将一些内容记录到控制台中,这应该足以满足您的要求

console.log('Look, ma, Node hands!')

const oneThroughFive = [1, 2, 3, 4, 5]

oneThroughFive.forEach(number => {
  console.log(number)
})

假设您保存了该代码,然后在终端窗口中打开命令行,导航到文件所在的目录(使用 cd 或“更改目录”),并运行 node test.js 以获取以下输出

Look, ma, Node hands!
1
2
3
4
5

您也可以只输入 node(后面没有文件名)打开一个交互式终端,您可以在其中运行任意的 Node JavaScript 代码。如果您曾经在浏览器 DevTools 中打开控制台输入一些代码,那么这 *完全* 类似,只是在命令行中使用 Node 代替。

如果您愿意,可以试一试,假设您已经安装了 Node。但同样,这仅仅是为了说明,对于使用 npm 来说并不必要。

A screenshot of an open terminal window showing Node version 17.0.1 running and the output from the previous example under it.

接下来是什么

本章中我们介绍的所有内容都非常有用,希望可以向您展示(即使是简单地)Node 的工作方式。请记住,虽然我们没有介绍任何具体的示例,但 Node 能够完成服务器端语言可以完成的任何事情。希望您不难想象,运行一些 JavaScript 代码来在系统级别甚至在远程服务器上执行几乎所有您可以想到的事情,是多么地吸引人且有利。

Node 的概念最初是作为一种在浏览器之外运行 JavaScript 的方法而诞生的。因此,我们拥有基于 Node 的脚本包,这些脚本包用于帮助我们进行前端开发。那么,我们如何安装这些包并确保它们不仅得到更新,而且可以卸载呢?这包含在 npm 缩写中的最后两个字母:package manager(包管理器)。

换句话说,npm 是一个用于管理用 Node JavaScript 编写的包的工具。什么是包管理器?npm 如何成为包管理器?这将在我们 npm 指南的下一部分中介绍。