前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2024 年,Node.js 依然处于霸主地位!

2024 年,Node.js 依然处于霸主地位!

作者头像
ConardLi
发布2024-07-12 17:21:29
2700
发布2024-07-12 17:21:29
举报
文章被收录于专栏:code秘密花园

大家好,我是 ConardLi

15 年来,Node.js 一直是 Web 开发的基石。自 2009 年发布以来,它已经支持超过 630 万个网站,98% 的《财富》500 强公司都在使用它。

作为一个强大的开源运行时环境,Node.js 建立在我们熟悉的 JavaScript 基础之上,拥有轻量级和事件驱动的架构。这使得它非常适合用来构建可以处理大量并发请求的可扩展的实时应用程序。

加上其活跃并且不断增长的开源社区,以及来自 OpenJS 基金会的强大支持,使其成为了现代 Web 开发的支柱。

但最近,关于 Node.js 衰退的传言开始流传起来,Bun、Deno 等强大的 JavaScipt 运行时环境如雨后春笋一样陆续推出,这是否意味着 Node.js 真的走向衰退了呢?

在今天这篇文章里,我们一起来深入研究一些关键指标,看看 Node.js 是否依然坚挺,以及再看一看已经发布和即将在 Node.js 上线的关键特性。

有些人可能会认为新的技术必然会淘汰掉旧的技术。但事实是,进步往往建立在现有的基础之上。以 COBOL 为例,这个在 1959 年创建的编程语言至今仍在被广泛使用。虽然它可能不是进行 Web 开发的首选,但 COBOL 对于维护银行、金融和政府机构的核心业务系统仍至关重要。根据最新的 Tiobe 指数,COBOL 的普及率依然正在增加,目前在 RubyRust 之间。它持久的相关性突显了一个关键点:技术进步并不总是意味着丢弃过去。

让我们考虑另一个在 Web 开发领域中的老牌选手:jQuery。这个 JavaScript 库比 Node.js 还要早三年发布,目前超过 95%JavaScript 网站和总体上 77% 的网站都在使用 jQueryjQuery 持久的流行表明,一个技术的年龄并不一定决定其相关性。就像 jQuery 一样,尽管 Node.js 年轻一些,但它同样有潜力保持其作为 Web 开发者宝贵工具的地位。

使用量

根据 StackOverflow 的调查,Node.js 依然是最受欢迎的技术。这种成功依赖于 Node.jsnpm 的强大组合。它们解决了大规模软件复用的挑战,这在以前是难以实现的。

因此,预先编写的代码模块的使用呈爆炸式增长,这也巩固了 Node. js 作为霸主的地位。

readable-stream 的下载量从 2022 年略超过30亿次增长到 2023 年接近70亿次,这意味着使用量在三年内翻了一番。

Node.js 每个月的下载量高达 1.3 亿次。

当然,其中很大一部分下载量实际上是头文件。这些头文件是在执行 npm i 命令期间临时下载的,用于编译二进制附加组件。一旦编译完成,这些附加组件会存储在你的系统中以供以后使用。

从操作系统的下载量来看,Linux 高居榜首。这也是合理的,因为 Linux 通常是持续集成(CI)- 软件在开发过程中进行的自动化测试过程的首选平台。尽管 Linux 在 CI 中占据主导地位,开源项目(OSS)通常也会在 Windows 上进行额外的测试以确保万无一失。

这个高下载量的趋势转化为实际使用情况。在 2021 年,Node.js 二进制文件的下载量为 3000 万次,这一数字在 2024 年跃升至 5000 万次。在 2023 年,Docker 中心上的 Node.js 镜像下载量超过了 8 亿次,这为我们提供了 Node.js 在生产环境中使用情况的重要参考。

安全性

许多开发者和团队在不知不觉中由于没有更新 Node.js 而使他们的应用程序面临风险,但是保持最新版本的更新还是非常重要的。

Node.js 提供了长期支持(LTS)计划,以确保关键应用程序的稳定性和安全性。然而,版本最终会达到其生命周期的终点,这意味着它们将不再接收安全补丁。这使得使用这些过时版本构建的应用程序容易受到攻击。

例如,Node.js 版本 14 和 16 现在已经被弃用。尽管如此,这些版本每月仍然有数百万次下载 —— 在2 月份,Node 16 被下载了 2500 万次,而 Node 14 被下载了大约 1000 万次。令人震惊的是,一些开发者甚至还在使用更旧的版本,如 Node 10Node 12

好消息是:更新 Node.js 非常简单。推荐的方法是每两个 LTS 版本进行一次升级。例如,如果你当前使用的是 Node.js 16(已不再支持),你应该迁移到最新的 LTS 版本,目前是 Node.js 20。不要让过时的软件使你的应用程序暴露在安全威胁之中。

安全修复程序按季度批量发布。去年,TSC 共收到 80 份意见书。

当然,这种对安全性的承诺离不开开源安全基金会(OpenSSF)的支持。通过由 Microsoft、GoogleAmazon 资助的 OpenSSF 领导的 Alpha-Omega 项目,Node.js 获得了专门用于提升其安全状况的资助。Alpha-Omega 项目于 2022 年启动,旨在通过更快地识别和解决漏洞,使关键的开源项目更加安全。这种合作关系,再加上 Node.js 专门用于安全工作的资金,展示了在保护 Node.js 用户安全方面的强烈承诺。

近年来发布的主要功能

ESM

Node.js 已经全面支持 ECMAScript 模块(ESM)。ESM 提供了一种更现代的代码结构方式,使代码更简洁、更易于维护。

ESM 的一个关键优势是能够在 import 语句中显式声明依赖项。这不仅提升了代码的可读性,还能帮助你清晰地了解项目依赖。正因如此,ESM 正快速成为新 Node.js 项目的首选模块格式。

下面是如何在 Node 中使用 ESM 模块的示例:

代码语言:javascript
复制
// conardLi.mjs
function addTwo(num) {
  return num + 17;
}

export { addTwo };

// app.mjs
import { addTwo } from './conardLi.mjs';

// Prints: 34
console.log(addTwo(17));

Threads

Node.js 还引入了 Worker Threads,让用户可以将复杂的计算任务卸载到独立的线程中。这可以解放主线程用于处理用户请求,从而带来更流畅和更具响应性的用户体验。

代码语言:javascript
复制
const {
  Worker,
  isMainThread,
  setEnvironmentData,
  getEnvironmentData,
} = require('node:worker_threads');

if (isMainThread) {
  setEnvironmentData('Hello', 'code秘密花园!');
  const worker = new Worker(__filename);
} else {
  console.log(getEnvironmentData('Hello'));  // Prints 'code秘密花园!'.
}

Fetch

Node.js 现在内置了 Fetch API 的实现,这是一种现代且符合规范的方式,用于通过网络获取资源。这意味着你可以编写更简洁、统一的代码,而无需依赖外部库。

Node.js 还引入了几个新功能来增强与 Web 平台的兼容性。这些功能包括:

  • Web Streams: 高效处理大型数据流,而不会压垮你的应用程序。
  • FormData: 轻松构建和发送表单数据进行网络请求。
  • StructuredClone(): 创建复杂数据结构的深拷贝。
  • TextEncoderTextDecoder: 无缝处理文本编码和解码任务。
  • Blob: 表示各种用途的原始二进制数据。
代码语言:javascript
复制
// 使用 Fetch API 进行网络请求
const fetch = require('node-fetch');

async function fetchData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  console.log(data);
}

fetchData();

// 使用 Web Streams 处理大数据流
const { WritableStream } = require('web-streams-polyfill/ponyfill/es2018');

const writableStream = new WritableStream({
  write(chunk) {
    console.log('接收到的数据块:', chunk);
  },
  close() {
    console.log('数据流处理完成');
  },
  abort(err) {
    console.error('数据流处理出错:', err);
  },
});

// 创建 FormData 并发送
const formData = new FormData();
formData.append('key', 'value');

fetch('https://api.example.com/submit', {
  method: 'POST',
  body: formData
}).then(response => response.json())
  .then(data => console.log(data));

// 使用 StructuredClone 创建数据的深拷贝
const structuredClone = require('structured-clone');
const originalData = { a: 1, b: { c: 2 } };
const clonedData = structuredClone(originalData);
console.log(clonedData);

// 使用 TextEncoder 和 TextDecoder 处理文本
const { TextEncoder, TextDecoder } = require('util');
const encoder = new TextEncoder();
const decoder = new TextDecoder('utf-8');

const encoded = encoder.encode('Hello, world!');
console.log(encoded);

const decoded = decoder.decode(encoded);
console.log(decoded);

// 使用 Blob 处理二进制数据
const { Blob } = require('buffer');
const blob = new Blob(['Hello, world!'], { type: 'text/plain' });

blob.text().then(text => console.log(text));

Promise

Node.js 提供了内置的 Promise 功能,为处理异步任务的结果提供了一种更简洁、更结构化的方式。

告别了回调地狱 — 使用 Promise,你可以编写更自然流畅、易于理解的代码。

下面是一个使用 fs/promises 模块中的 readFile 方法的实用示例:

代码语言:javascript
复制
const fs = require('fs/promises');

async function readFileAsync(filePath) {
  try {
    const data = await fs.readFile(filePath, 'utf8');
    console.log('文件内容:', data);
  } catch (error) {
    console.error('读取文件时出错:', error);
  }
}

// 调用示例
readFileAsync('./example.txt');

Node.js 核心模块

Node.js 引入了 node: 前缀为核心模块建立了一个清晰的区分,使核心模块和用户引入的模块区别更加明显。

这个前缀就像一个标签,瞬间将一个模块标识为 Node.js 的核心构建模块。这一改变给开发者带来了几个好处:

  • 减少混淆: 不再将核心模块误认为是用户创建的模块。
  • 简化选择: 使用 node: 前缀可以轻松挑选特定的核心模块。
  • 命名空间保护: 防止用户在 npm 注册表中占用可能与未来核心模块冲突的名称。

下面是如何使用 node: 前缀导入核心模块的示例:

代码语言:javascript
复制
import test from 'test';
import assert from 'assert';
Vs 

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

Watch

在引入此功能之前,nodemon 是用于监视文件更改的最流行的软件包。

现在,--watch 标志可以提供下面的功能:

  • 自动文件监听:它会监视你导入的文件,以便在发生任何更改时立即采取行动。
  • 即时重新启动:每当修改监视的文件时,Node.js 都会自动重新启动,确保您的应用程序反映最新更新。
  • 测试协同: --watch 标志可以很好地配合你的测试运行程序,在文件更改后自动重新运行测试。这允许无缝的开发工作流程和持续的反馈。

为了进行更精细的控制,--watch-path 标志可以让你准确指定要监视的文件。

AsyncLocalStorage

AsyncLocalStorage 允许在 Web 请求的整个生命周期或任何其他异步持续时间内存储数据。它类似于其他语言中的线程本地存储。

AsyncLocalStorage 使我们能够创建 React Server 组件这样的功能,它充当了 Next.js 请求存储的基础。这些组件简化了 React 应用程序中的服务器渲染,最终改善了开发者的体验。

代码语言:javascript
复制
import http from 'node:http';
import { AsyncLocalStorage } from 'node:async_hooks';

const asyncLocalStorage = new AsyncLocalStorage();

function logWithId(msg) {
  const id = asyncLocalStorage.getStore();
  console.log(`${id !== undefined ? id : '-'}:`, msg);
}

let idSeq = 0;
http.createServer((req, res) => {
  asyncLocalStorage.run(idSeq++, () => {
    logWithId('start');
    // Imagine any chain of async operations here
    setImmediate(() => {
      logWithId('finish');
      res.end();
    });
  });
}).listen(8080);

http.get('http://localhost:8080');
http.get('http://localhost:8080');
// Prints:
//   0: start
//   1: start
//   0: finish
//   1: finish

WebCrypto

这个标准化 API 直接在 Node.js 环境中提供了一组强大的加密工具。

借助 WebCrypto,我们可以利用以下功能:

  • 密钥生成:创建强大的加密密钥来保护你的数据。
  • 加密和解密:对敏感信息进行加密以确保安全存储和传输,并在需要时进行解密。
  • 数字签名:对数据进行签名以确保真实性并防止篡改。
  • 生成 Hash:生成唯一的数据指纹以进行验证和完整性检查。

通过将 WebCrypto 合并到 Node.js 应用程序中,我们可以显着增强其安全状况并保护用户的数据。

代码语言:javascript
复制
const {subtle} = require('node:crypto').webcrypto;

(async function () {
const key = await subtle.generateKey({
name:'HMAC',
hash: 'SHA-256',
length: 256
}, true, ['sign', 'verify'] )

const enc = new TextEncoder();
const message = enc.encode('I love cupcakes');

const digest = await subtle.sign({
name: 'HMAC'
}, key, message)

}) ()

Utils.ParseArgs()

Node.js 提供了一个名为 Utils.ParseArgs() 的内置实用程序(或 node:util 模块中的 parseArgs 函数),它简化了在应用程序中解析命令行参数的任务。这消除了对外部模块的需求,使我们的代码库更加精简。

它接受传递给 Node.js 脚本的命令行参数,并将它们转换为更可用的格式,可以让我们轻松地在代码中访问和使用这些参数。

代码语言:javascript
复制
import { parseArgs } from 'node:util';
const args = ['-f', '--bar', 'b'];
const options = {
  foo: {
    type: 'boolean',
    short: 'f',
  },
  bar: {
    type: 'string',
  },
};
const {
  values,
  positionals,
} = parseArgs({ args, options });
console.log(values, positionals);
// Prints: [Object: null prototype] { foo: true, bar: 'b' } []

权限模型

Node.js 进程对系统资源的访问及其可以使用这些资源执行的操作可以通过权限进行管理。其他模块可以访问哪些模块也可以通过权限来管理。

代码语言:javascript
复制
process.permission.has('fs.write');
//true
process.permission.deny('fs.write', '/home/user');

process.permission.has('fs.write');
//true
process.permission.has('fs.write', '/home/user');
//false

详细可以看这篇文章:Node.js 20 为啥要搞个权限模型?到底有啥用?

require(esm)

一个新的标志已经发布,允许开发人员同步使用 ESM 模块。

代码语言:javascript
复制
'use strict'

const {answer} = require('./esm.mjs')
console.log(answer)

此外,新标志 --experimental-detect-module 允许 Node.js 检测模块是 commonJS 还是 esm。这个新标志简化了用 Javascript 编写 Bash 脚本。

CommonJS 和 ES Module 终于要互相兼容了???

最后

  • 参考:https://blog.platformatic.dev/nodejs-is-here-to-stay

大家还在使用 Node.js 吗,对 Node.js 的未来怎么看?欢迎在评论区留言。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 code秘密花园 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用量
  • 安全性
  • 近年来发布的主要功能
    • ESM
      • Threads
        • Fetch
          • Promise
            • Node.js 核心模块
              • Watch
                • AsyncLocalStorage
                  • WebCrypto
                    • Utils.ParseArgs()
                      • 权限模型
                        • require(esm)
                        • 最后
                        相关产品与服务
                        持续集成
                        CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档