The ordinary know how, but the standout know why.
普通的开发者知道怎么做,但杰出的开发者知道为什么
关于主题
准备开一个新的系列,名为《Nodejs开发进阶》。
这个课题的内容可能会非常丰富,所以现阶段很难一次性就规划出所有需要包括的内容,所以显然是需要写成系列的形式。此外,笔者不想使用另外一个名词-高级,是因为觉得这里阐述的内容其实没有什么神秘或者高级,只是一些基础和基本的内容,也是每一个开发者在一定的发展阶段必须要理解和掌握的内容。但在现实的世界中,由于开发者的懒惰和路径依赖,在很多情况下,并没有很好的理解这些内容,所以也不能很好的在实际的开发工作中很好的应用。笔者其实也经过或者正在持续的经历这个阶段,也感觉到,进阶也是一个持续和循环的过程。
所以本系列也不会讨论太基础的问题,是为有一定基础,但可能需要在某些方面进行提升,或者需要一些新的认知和技术来提高开发和工作效率,甚至追求程序和代码架构美感的读者准备的。笔者假设读者对于Nodejs系统和Web应用开发已经有了一些基本的理解和经验,但可能对系列中的内容或者组成部分缺乏使用的经验或者正确的认知,需要更深入的理解。当然也欢迎读者如果觉得文中内容不妥或者有更好的表述方式,可以给笔者一些有益的建议和反馈,大家共同进步。
对于系列内容的选择,笔者的想法是这样的。这些内容并不是完全必须的,但是理解和掌握这些内容,可以帮助开发人员更好的理解程序运行和软件开发的过程,提升对于计算机科学和软件工程的认知,构建更为科学、合理、高效的知识和技能框架。最终的目的是提高开发人员使用信息技术和工具解决实际业务问题的能力和效率。
本系列的主题,基本上都是围绕着Nodejs这一系统平台展开的。可能也会稍微外溢,包括比如JS语言,V8执行引擎,TCP/IP网络技术,数据库等,如果笔者觉得有必要,就可以涉及。关于Nodejs,最重要的参考资料和信息来源,当然就是其官方网站和官方技术文档集合。主要的参考版本是当前的LTS版本,它们的链接如下:
那么,作为本系列的开篇,我们当然想要从一个进阶的角度,先来聊聊这个nodejs了。
对Nodejs的理解
在其官方网站上,对于nodejs是这样描述的(译文):
Node.js® 是一个开放源代码,跨平台的Javascript运行环境。
这个叙述虽然简单,但笔者觉得还是太过平淡了,并没有突出它的很多特点,也遗漏了很多重要的信息。所以,笔者尝试对其进行展开和说明如下:
- Node.js才是这个技术体系的学名,我们简称为nodejs或者node
- 开放源代码,nodejs主要使用MIT开源协议
- 狭义的nodejs是一个运行环境,基于V8引擎来支撑JavaScript程序的运行
- 广义的nodejs是一个技术生态系统,包括了相关内置配套和扩展的程序库、功能模块、开发和管理工具等等
- 基于nodejs开发使用的是JS语言;但构建nodejs本身,主要使用C++和JS语言(一些功能模块)
- JS代码的执行环境是V8,这一点在nodejs和浏览器环境中是相同的,这样可以大大提高前后端开发的兼容性
- nodejs是跨平台的,支持所有主流操作系统平台,并且其程序在这些平台上运行的差异很小,可能是因为浏览器本身需要跨平台,所以JS和V8都需要跨平台
- nodejs主要是为Web应用开发而设计的,因此它内置了很多相关的功能库和模块,如net、http、crypto等等,而不是一个最基本的程序语言和运行环境
- 和传统序列化执行程序不同,js程序执行的特点是异步执行、事件驱动
- 基于js程序本身的特点,和V8对JS代码执行的良好优化,nodejs程序在性能、启动和资源占用方面的表现优异,特别适合于Web应用这种高密度请求响应的执行模式
Nodejs技术文档结构
要想更加综合和全景的了解nodejs的技术框架,直接查看其官方技术文档,是一个比较好的方式。看这个目录,就可以大概知道nodejs的技术涉及到那些方面(以V20版本为例),也可以让我们能够更深刻的体会nodejs技术的全面和丰富:
| 主题 | 说明 |
|---|---|
| Assertion testing | 断言测试,用于开发时编写测试用例或调试使用 |
| Asynchronous context tracking | 异步上下文跟踪 |
| Async hooks | 异步钩子 |
| Buffer | 缓冲,字节数组 |
| C++ addons | C++插件 |
| C/C++ addons with Node-API | C++插件带Node-API |
| C++ embedder API | C++嵌入API |
| Child processes | 子进程,可用于调用外部程序 |
| Cluster | 进程群集,可用于创建多个nodejs程序实例 |
| Command-line options | 命令行选项,可以设置node执行环境和选项 |
| Console | 控制台,用户输出调试信息 |
| Corepack | nodejs程序包配置管理工具 |
| Crypto | 密码学套件,基于OpenSSL程序库 |
| Debugger | 调试器,用于nodejs程序调试 |
| Deprecated APIs | 过时API |
| Diagnostics Channel | 诊断通道,可用于调试,监控和性能分析等等 |
| DNS | 域名系统,但只是系统调用,而非DNS协议实现 |
| Domain | 域,此功能已过时 |
| Errors | 错误处理 |
| Events | 事件系统 |
| File system | 文件系统 |
| Globals | 全局变量 |
| HTTP | HTTP协议 |
| HTTP/2 | HTTP2协议 |
| HTTPS | HTTPS协议 |
| Inspector | 调试查看器 |
| Internationalization | 国际化 |
| Modules: CommonJS modules | CommonJS模块 |
| Modules: ECMAScript modules | ECMA模块 |
| Modules: node:module API | node模块API |
| Modules: Packages | 包模块 |
| Net | 基础网络协议 |
| OS | 操作系统相关 |
| Path | 路径 |
| Performance hooks | 性能挂钩 |
| Permissions | 权限 |
| Process | 进程 |
| Punycode | HTTP2协议 |
| Query strings | 查询字符串 |
| Readline | 行读取 |
| REPL | 快速交互执行环境 |
| Report | 报告 |
| Single executable applications | 单一可执行程序 |
| Stream | 流处理 |
| String decoder | 字符串解码器 |
| Test runner | 测试执行器 |
| Timers | 计时器 |
| TLS/SSL | 安全套接字 |
| Trace events | 跟踪事件 |
| TTY | 终端 |
| UDP/datagram | UDP协议,数据报 |
| URL | URL地址 |
| Utilities | 实用工具 |
| V8 | V8执行引擎 |
| VM | HTTP2协议 |
| WASI | HTTP2协议 |
| Web Crypto API | Web密码学API |
| Web Streams API | Web流API |
| Worker threads | 工作线程 |
| Zlib | Zlib压缩库 |
看到这个阵容,懂行的人都应该可以看除了,理论上而言,基于nodejs,可以在不引用或者依赖第三方应用程序的情况下,就可以构建一个功能丰富的Web应用,当然如果要连接或者操作第三方应用系统(比如数据库系统),就可能需要第三方系统提供的程序库。但这也使整个系统构建的工作,可以简化到一个很少的程度。
nodejs生态系统
当然,围绕nodejs,还有一个庞大而成熟的生态系统。nodejs提供了一个强大、完善而易用的程序包管理机制(Node Package Manager),类似于linux世界中的apt或者yum。通过npm,开发者可以基于开源社区,充分利用网络上已有的开发资源和别人已经构建好的功能模块,快速的给自己的应用程序集成各种各样更加丰富的功能,极大的提高了应用开发的效率。比如我们最常用的Web应用开发框架,就有很多的选择,比如express、hapi、fastify等等。下表列举了笔者在日常业务系统开发中常用的一些功能模块和npm包库选项:
| 功能模块 | 包和库 | 说明 |
|---|---|---|
| Web应用框架 | fastify | 高性能API开发首选 |
| Web应用框架 | express | 应用最广泛, nodejs web框架的标准 |
| Web应用框架 | totaljs | 笔者早期使用,非常有特点和全面的web框架 |
| Postgres数据库客户端 | pg | 提供连接池,游标等功能 |
| Oracle数据库客户端 | oracledb | 官方库,需要 client lib |
| MQTT服务客户端 | mqtt | 可以集成并使用MQTT服务 |
| REDIS服务客户端 | redis | 可以集成并使用redis服务 |
| minio服务客户端 | minio | 可以集成并使用minio或者s3存储服务 |
| 大型高性能KV缓存 | megahash | 使用C++实现的高性能hashtable,不占用V8堆空间 |
| 验证码生成 | svg-captcha | svg验证码图片生成 |
| 二维码生成 | qrcode | 用于生成二维码,条码现在使用的都比较少了 |
| 简单图形处理 | sharp | 简单的图形处理 |
| 同步异步处理 | async | 常用的有serise,queue 等,功能丰富 |
| 同步异步处理 | promise/async/await | 内置库,优先使用 |
| http请求 | axios | 使用最广泛 |
| http请求 | http, fetch | 原生内置库,优先使用 |
| 定时任务 | node-schedule | 类似cron的定义方式 |
| 定时任务 | timer | 原生内置类型,优先使用 |
| 密码学 | crypto | 内置库 |
| 密码学 | nacl | 另一个优异的密码学算法库,支持ecc和chacha20-poly1305 |
| 密码学 | sjcl | 笔者早期使用的密码学库,前端可用 |
| 文件系统和操作 | fs | 内置库 |
| websocket | socket.io | 功能丰富完善,原生ws模块太弱 |
| 执行管理 | pm2 | 生产环境中的运行管理 |
| 性能测试 | autocannon | 命令行和程序性能和压力测试 |
| 测试框架 | jest | 评价较高,准备尝试使用 |
| 文件压缩 | node-7z | 使用较多,支持7z,zip和rar,在合适场景下准备尝试使用 |
最后,接着例举和概览nodejs的生态系统,刚好可以简单分享一下笔者选择解决方案和技术工具的原则和方法论:
- 尽量减少在开发和移植过程中的外部引用和维护,减少外部代码和库的使用
- 在没有特别要求的情况下,优先选择系统内置和原生技术,如async、fs、crypto等等都是nodejs内置模块
- 对于特别简单的应用,或者使用场景非常少的需求,可以考虑编写代码实现,而非使用和引用外部代码
- 优先选择开源的,跨平台的技术,因为可能在出现深层次问题的时候,找到原因或者根源
- 简洁优雅,逻辑清晰,有明确的结构和框架
- 如果确实要引用外部程序,可以把查看npm在github中下载的数量(或者打星的数量),代码文档的完善丰富程度,提供示例代码的合理性等等,作为技术评估的标准和方法
后续内容
本文并没有着力从技术性的方面来分享nodejs所涉及到的相关技术细节,而是先给大家一个总体的框架和全貌,让大家能够理解,nodejs作为一个相对比较新和现代化的应用程序体系,它可以一开始就有一个完善的架构和比较高的起点,并且在实践和应用中证明了这一点,是可以作为主流的Web开发技术的代表和引领其发展方向的。
在后面的章节中,我们会逐渐深入技术细节,来揭示nodejs是如何做到这些的。
2024年4月18日,更新已完成的内容包括:
- Nodejs开发进阶1-Nodejs
- Nodejs开发进阶2-架构理解
- Nodejs开发进阶3-Buffer
- Nodejs开发进阶4-V8
- Nodejs开发进阶5-JavaScript编程语言
- Nodejs开发进阶6-Stream
- Nodejs开发进阶7-文件系统
- Nodejs开发进阶8-操作系统
- Nodejs开发进阶9-REPL
- Nodejs开发进阶A-Console
- Nodejs开发进阶B-进程和线程
- Nodejs开发进阶C-HTTP
- Nodejs开发进阶D-Crypto
- Nodejs开发进阶E-Crypto之非对称加密
- Nodejs开发进阶F-Event
- Nodejs开发进阶G-部署和管理
- Nodejs开发进阶H-Package.json
- Nodejs开发进阶I-PM2
- Nodejs开发进阶J-计时器
- Nodejs开发进阶K-Util工具类
- Nodejs开发进阶L-异步执行和优化机制