likes
comments
collection
share

Node.js 知识体系(一):基础概念、历史与应用场景Nodejs 的概念 Node.js 是一个基于 Chrome

作者站长头像
站长
· 阅读数 33

Nodejs 的概念

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,它让开发者可以在服务端使用 JavaScript 构建高效、可扩展的网络应用。Node.js 采用非阻塞、事件驱动的 I/O 模型,使其非常适合处理高并发的场景,如实时应用、API 服务等。由于其轻量级和高性能,Node.js 常被用于构建微服务架构、BFF 层等现代 Web 应用中的关键组件。

非阻塞 (Non-blocking) :传统的 I/O 操作是同步的,程序在执行某个 I/O 操作时(比如读取文件或从数据库获取数据),需要等待操作完成后才能继续执行其他任务。这种方式称为阻塞。而非阻塞 I/O 则不同,它在发起 I/O 请求时,不需要等待操作完成,而是立即返回,程序可以继续执行其他任务。这样,系统的资源不会被浪费在等待上。

事件驱动的 I/O 模型: 在非阻塞 I/O 中,当 I/O 操作完成后,会触发一个事件,并调用相应的回调函数来处理这个事件。Node.js 的事件循环(Event Loop)就是负责监控这些 I/O 操作,并在合适的时候将事件分发给相应的回调函数处理。这样,代码执行变得更加高效,能够同时处理大量并发的请求。

这套模型的核心就是通过让 I/O 操作异步进行,避免了传统同步操作中的阻塞问题,大大提升了系统的性能和响应速度。对于高并发场景,如处理大量网络请求时,非阻塞、事件驱动的 I/O 模型能有效提高吞吐量。

Nodejs 的演变历史

Node.js 于 2009 年由 Ryan Dahl 开发,最初的目标是为了解决传统服务器处理高并发请求时的效率问题。早期的服务器(如 Apache)大多采用多线程或同步阻塞的模型,在处理大量请求时容易遇到性能瓶颈。Node.js 的出现,通过引入非阻塞、事件驱动的 I/O 模型,使得 JavaScript 不仅可以用于前端开发,还能用于高效的服务端编程。随着 NPM(Node Package Manager)的发布,Node.js 社区蓬勃发展,吸引了大量开发者贡献模块和工具,使其迅速成为构建现代 Web 应用、微服务架构及实时应用(如聊天、在线游戏)的热门技术栈。

Nodejs 的应用场景

作为一名前端开发, 我们每天都在使用 node 来辅助开发。

首先,Node.js 常用于构建开发工具和自动化流程,比如 Webpack 用于打包、Babel 用于编译 ES6 代码、ESLint 用于代码格式检查,这些工具都依赖于 Node.js 的执行环境。

其次,Node.js 被广泛应用于服务端开发,特别是构建轻量级、高并发的 API 服务,比如 Express.js 常用于快速构建 RESTful API,Koa.js 适合微服务架构。

再次,Node.js 的非阻塞 I/O 模型非常适合构建实时应用,例如 Socket.io 能轻松实现即时通讯和在线多人游戏。

此外,Node.js 也可以用于全栈开发,结合前端的 React 或 Vue,像 Next.js 和 Nuxt.js 这样的框架允许我们开发同构应用,提升用户体验和 SEO 性能。因此,Node.js 已经成为现代前端开发中的重要组成部分。

排除一些其他的类 node 框架, 所有非浏览器下的 js 执行都和 node 有关。

  • 跨平台开发: PC, web, H5, RN, weex
  • 后端开发: API, RPC, koa, express
  • 前端开发: 构建工具 webpack, vite, babel
  • 工具开发: 脚本, 脚手架, 命令行等等

Nodejs 生态系统

Node.js 的生态系统丰富,涵盖了许多用于不同场景的工具和库。以下是按功能分类的一些常见工具和库:

压缩工具

Terser:现代化的 JavaScript 压缩工具,继承了 UglifyJS 的许多功能,但支持 ES6+ 语法,性能和压缩效果较好。

Babel Minify(原名 Minify):Babel 官方支持的压缩工具,集成了 Babel 转译器和压缩功能,适用于现代 JavaScript 代码的压缩。

Google Closure Compiler:Google 提供的高级 JavaScript 压缩工具,提供严格的压缩和优化功能,但配置较复杂。

UglifyJS:用于 JavaScript 代码的压缩与混淆,减少代码体积,提高加载速度。

JSMinify:轻量级的 JavaScript 压缩工具,能有效减少无用的空格和注释,提升代码执行效率。

HTMLMinifier:高效的 HTML 压缩工具,能够去除不必要的空格、注释,并优化 HTML 结构。

Minify:提供 HTML、CSS、JavaScript 的综合压缩功能,适用于多种文件类型的处理。

依赖管理

pnpm:高效的包管理工具,通过硬链接和全局缓存来加速依赖安装,节省磁盘空间。

Yarn:Facebook 提供的包管理工具,作为 npm 的替代品,具有更快的安装速度和更好的缓存管理。

npm(Node Package Manager):Node.js 的官方包管理器,广泛用于安装、管理项目依赖以及发布库。

Bower:早期的前端包管理器,用于管理 Web 项目依赖,但现在已逐渐被 npm 和 Yarn 替代。

模块系统

SystemJS:一个通用的模块加载器,支持多种模块格式(包括 AMD、CommonJS、ESM),可用于在浏览器和 Node.js 环境中加载模块。

CommonJS:Node.js 默认的模块系统,允许开发者通过 require 和 module.exports 进行模块加载与导出。

ESM(ECMAScript Modules):标准化的模块系统,支持 import 和 export,Node.js 从 v12 开始支持。

CSS 处理

CSSO(CSS Optimizer):用于优化和压缩 CSS,支持多种 CSS 处理功能,如合并选择器、去除重复规则等。

Clean-CSS:高效的 CSS 压缩工具,能去除冗余的 CSS 规则和空格,支持高级的 CSS 处理功能。

PostCSS:一个功能强大的工具,允许使用插件进行 CSS 预处理、自动加前缀、CSS 变量替换等操作。插件如 Autoprefixer 可自动处理兼容性问题。

构建工具

Parcel:零配置的 Web 应用打包工具,支持热模块替换、代码分割等功能,适用于快速原型开发和小型项目。

Gulp:基于流(stream)的自动化构建工具,简化了文件处理和任务管理,常用于 CSS、JS 文件压缩、转码、自动化测试等。

Grunt:早期的任务自动化工具,配置简单,但逐渐被 Gulp 和 Webpack 取代。

Webpack:功能强大的模块打包工具,支持静态资源模块化、代码分割、热模块替换等现代 Web 开发功能,广泛应用于 React、Vue 项目。

Rollup:主要用于打包 JavaScript 库,支持 ES6 模块,生成的输出文件体积较小,适合构建现代化 JavaScript 库。

模板引擎

Nunjucks:功能强大的模板引擎,支持继承、过滤器、宏等功能,适用于复杂的模板需求。

EJS:简单的 JavaScript 模板引擎,允许在模板中插入 JavaScript 代码,适合简单的模板渲染需求。

Jade(现更名为 Pug):简洁的模板引擎,允许开发者通过缩进来编写 HTML,支持变量插值和逻辑控制。

Handlebars:逻辑简单的模板引擎,基于 Mustache 模板,允许通过占位符 {{}} 来插入数据,常用于前后端渲染。

跨平台应用开发

Electron:基于 Node.js 和 Chromium,用于构建桌面应用程序的框架。著名的应用如 Visual Studio Code 和 Slack 都是基于 Electron 构建的。

Tauri:相比 Electron 更轻量,基于 Rust 和 WebView,用于构建小体积、高性能的跨平台桌面应用。

Capacitor:由 Ionic 团队开发的跨平台应用框架,支持构建移动端和桌面应用,适用于与 Ionic 框架结合使用。

React Native:用于构建原生移动应用的框架,允许使用 React 构建跨平台的 iOS 和 Android 应用。

Node 和 浏览器的区别

Node.js 和浏览器环境有显著的区别,主要体现在它们提供的功能和用途上。Node.js 环境中不包含浏览器特有的 DOM(文档对象模型)和 BOM(浏览器对象模型),因此不能直接操作网页中的 HTML 和浏览器窗口。而浏览器则没有 Node.js 提供的 fs(文件系统)、path 和 http 等模块,这些模块用于服务器端的文件操作、路径处理和网络请求。

关于在 Node.js 中实现 GUI(图形用户界面),虽然理论上可以,但通常不这样做,因为 JavaScript 本身已经天然支持浏览器渲染,更高效的做法是使用 Electron 等框架,这些框架将浏览器封装进应用程序中,从而实现跨平台的桌面应用。

至于浏览器对磁盘的访问,出于安全考虑,浏览器无法直接调用磁盘操作,以避免恶意网页对用户数据的破坏。然而,浏览器可以通过限制的方式提供一些功能,如文件上传()等,允许用户主动选择文件上传至服务器,这种设计兼顾了用户体验和安全性。

Nodejs 存在的问题

Node.js 是一个强大的运行时环境,但也存在一些固有的挑战和局限性。

单线程模型

问题:Node.js 使用单线程事件循环模型来处理并发请求,这使得它在处理计算密集型任务时可能会遇到性能瓶颈。一个 CPU 密集型的操作可能会阻塞事件循环,从而影响整体的应用性能。

解决方案:虽然 Node.js 本身是单线程的,但可以通过 Cluster 模块和 PM2 等工具实现多进程并行处理。Cluster 模块可以创建多个进程来利用多核 CPU,而 PM2 提供了进程管理、负载均衡等功能,帮助提高应用的可扩展性和稳定性。

数据库支持

问题:Node.js 对 MongoDB、MySQL 和 Redis 的支持较为成熟,拥有丰富的库和工具,如 Mongoose(用于 MongoDB)、Sequelize(用于 MySQL)、ioredis(用于 Redis)。然而,对于某些其他数据库,如 Neo4j(图数据库)和 TigerGraph(图数据库),Node.js 的支持和工具可能相对较少,社区资源和文档也不如主流数据库那样丰富。

解决方案:虽然对这些数据库的支持可能不如主流数据库,但依然可以通过使用相关的库(如 neo4j-driver 和 tigergraph-client)来实现基本的连接和操作。同时,社区和开源项目也在不断改善这些支持,并提供了有用的工具和指南。

安全问题

问题:Node.js 应用面临各种安全挑战,包括但不限于输入验证不足、跨站脚本攻击(XSS)、跨站请求伪造(CSRF)、不安全的依赖项等。由于 Node.js 的广泛使用,攻击者也可能针对其生态系统中的库和框架进行攻击。

解决方案:为了提高安全性,开发者应遵循安全最佳实践,包括:

  • 使用 HTTPS 加密数据传输。
  • 对用户输入进行严格验证和消毒,防止 XSS 和 SQL 注入。
  • 定期更新依赖项,使用工具(如 Snyk、npm audit)扫描已知的漏洞。
  • 采用安全的编码习惯,防范 CSRF 攻击,并对敏感数据进行加密存储。

Node 可以做服务器, 为什么很少有公司用 node 作为后端语言呢?

性能问题

计算密集型任务:Node.js 使用单线程事件循环模型,虽然对于 I/O 密集型操作表现优秀,但对于计算密集型任务(如复杂的计算或数据处理)可能不如多线程的语言(如 Java、C#)高效。在需要高性能计算的场景中,其他语言可能更具优势。

内存限制:Node.js 的单线程模型可能在处理大型数据集或内存密集型操作时遇到瓶颈,特别是在资源消耗较高的应用中。

生态和成熟度

企业级应用:某些公司可能依赖于成熟的、功能丰富的企业级后端技术,如 Java 的 Spring Framework 或 .NET,这些技术具有广泛的社区支持和成熟的生态系统,适合大规模的企业应用。

现有技术栈:许多公司已经建立了稳定的后端基础架构,迁移到 Node.js 可能涉及重大的技术和人力资源投资,因此可能不会轻易更换现有的技术栈。

工具和库的成熟度

框架支持:虽然 Node.js 生态系统中有许多优秀的库和框架,但某些企业级功能和解决方案(如高性能计算、大数据处理、复杂的事务管理)可能在其他技术栈中更为成熟和完善。

开发团队的经验和技术债

团队技能:公司可能拥有具有特定语言(如 Java、C#、Python)经验的开发团队,转向 Node.js 可能需要培训和重新学习,这可能带来额外的成本和挑战。

技术债:已有项目和系统中积累的技术债务和复杂性可能使得转向 Node.js 的成本过高,特别是在大型、复杂的企业环境中。

安全和稳定性

安全性:Node.js 在处理并发时表现出色,但由于其事件驱动的非阻塞模型,可能需要额外的安全和稳定性考虑,例如对防止阻塞操作和处理异常的额外注意。

长期支持:一些企业级技术栈(如 Java、.NET)具有长期的企业支持和稳定性保证,而 Node.js 作为相对较新的技术,可能需要企业对其长期支持和稳定性的评估。

转载自:https://juejin.cn/post/7410668201778528275
评论
请登录