
从零上手 Node.js模块、HTTP 服务器、文件系统与事件机制实战指南【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum导读本篇指南以 Node.js 的入门学习路径为主线系统讲解在 Node.js 中运行脚本、创建与使用模块、用 HTTP 模块搭建基础 Web 服务器、用 fs 模块读写文件、用 URL 类解析地址以及使用 EventEmitter 处理事件等核心能力。读完本篇后你将能够脱离浏览器、纯用 JavaScript 编写可在本机或服务器上运行的后端程序并为课程末尾的 Basic Informational Site基础信息站点项目打下完整基础。本文基于仓库中的 getting_started.md 一课展开并辅以同一课程路径下的 introduction_what_is_nodeJS.md、environment_variables.md、debugging_node.md 与 project_basic_informational_site.md 进行深化。前置准备为什么先学 JavaScript 再学 Node在动手之前需要明确一个基本事实Node.js 本质上就是 JavaScript。正如 getting_started.md 开头强调的只有具备基本的 JavaScript 基础才能理解 Node 的语法与行为。Node 并不是一门新语言而是一个把 JavaScript 从浏览器中解放出来的运行时。这一点在 introduction_what_is_nodeJS.md 中有更详细的阐述JavaScript 最初被设计为只能在浏览器内运行这导致它无法编写网站以外的任何程序。Node 的出现让开发者可以用 JavaScript 完成 Ruby、PHP、C#、Python 等传统服务端语言能够完成的几乎所有事情——在本地计算机或服务器上直接运行 JavaScript而无需经过浏览器。为了支撑服务端场景Node 在浏览器 JavaScript 之外额外提供了一些能力其中包括读取和写入本地文件创建 HTTP 连接监听网络请求。本章的学习目标非常明确来自原文的 Lesson overview说明 Node.js 的常见用途创建和使用模块既包括内置模块也包括用户自定义模块使用 HTTP 模块搭建基础 Web 服务器从 Node.js 中读取、创建、更新和删除文件使用 URL 模块解析网址并将其拆分为可读部分理解如何使用 NPM创建、触发并监听自己的事件。理解 Node 的异步与事件驱动模型在编写第一段服务端代码前有必要先理解 Node 的运行哲学。Node 官网将其定义为异步事件驱动的 JavaScript 运行时这个定义可以拆解为两层含义异步asynchronous写代码时不需要预测每一行代码的精确执行顺序。程序被组织为一系列小函数这些函数在特定事件如网络请求发生时被调用事件驱动event driven程序在等待某个过程完成时并不阻塞后续代码而是坐等事件发生事件一到就触发对应的回调函数。introduction_what_is_nodeJS.md 给出了一个非常直观的例子假设程序需要从文件读取文本 → 打印文本内容以及查询数据库用户列表 → 按年龄过滤用户。如果同步执行必须逐条等待而异步执行时Node 会在等待文件读取的过程中立即启动数据库查询两个任务并行推进谁先完成谁先触发后续回调程序员无需关心二者的完成顺序。这与前端 JavaScript 中使用addEventListener等待鼠标点击或键盘按键的思路几乎一致区别只在于 Node 监听的事件是网络请求和数据库查询这类服务端事件而这一机制正是通过**回调函数callbacks**实现的。下面这段代码就是整个课程中最早的 Node 服务端示例http.createServer(function (req, res) { res.writeHead(200, {Content-Type: text/html}); res.end(Hello World!); }).listen(8080);这段代码创建了一个服务器并声明每当收到一个网络请求就执行这个回调函数。回调函数向客户端返回文本Hello World!。在浏览器中访问正确的地址和端口就能在屏幕上看到这行文本。它也是下一篇 HTTP 模块的主角。在终端中运行 Node.js 脚本入门的第一步是学会从命令行运行 Node 脚本。与浏览器中通过script标签加载 JavaScript 不同Node 脚本是独立的文件通过node命令直接执行node your-script.js例如把上面的 HTTP 示例保存为server.js然后在项目目录下执行node server.jsNode 就会启动这个脚本并保持监听。需要中断运行时在终端按下Ctrl C即可。从仓库中可以看到后续课程大量使用这种命令行驱动的工作流例如 introduction_to_express.md 中通过node app.js启动 Express 服务器environment_variables.md 中则展示了NODE_ENVprod node index.js这类带环境变量的运行方式。这说明运行 Node 脚本是贯穿整个 Node.js 课程的基础操作。内置模块与用户自定义模块Node 的功能是以模块为单位组织的。模块化意味着你可以把可复用的代码封装成独立文件在需要的地方引入。Node 的模块体系分为两类内置模块Node 自带如http、fs、url、events、path等直接require即可使用无需安装用户自定义模块你自己编写并导出的代码文件通过module.exports导出、通过require(./path)引入。一个典型的用户自定义模块如下// math.js function add(a, b) { return a b; } module.exports { add };// index.js const { add } require(./math); console.log(add(2, 3)); // 5这种按需引入、职责分离的组织方式正是后面课程中拆分路由、控制器等代码结构的基础。接下来几节将逐一介绍入门必备的四个内置模块。HTTP 模块创建基础 Web 服务器HTTP 模块是 Node 服务端编程的核心。它提供了创建 HTTP 服务器和发起 HTTP 请求的能力。使用 http.createServer 创建服务器http.createServer是 HTTP 模块中最常用的方法它创建一个 HTTP 服务器并接收一个处理函数handler该处理函数会在每次收到请求时被执行。如原文所述createServer方法创建一个 HTTP 服务器该服务器接收每次收到请求时都会执行的处理函数。服务器对象本身具备listen方法用于指定监听端口。综合前文一个最小可运行的服务器如下const http require(http); http.createServer(function (req, res) { res.writeHead(200, {Content-Type: text/html}); res.end(Hello World!); }).listen(8080);这里有几个要点req是请求对象包含客户端发来的方法、URL、请求头等信息res是响应对象res.writeHead用于写入状态码如200表示成功和响应头如Content-Type: text/htmlres.end结束响应并发送正文.listen(8080)让服务器监听本机 8080 端口访问http://localhost:8080即可看到响应内容。发起 HTTP 请求服务端场景不仅需要接收请求也常常需要主动向外发起请求例如调用第三方 API。Node 提供了fetch基于浏览器同款 Fetch API等能力用于发起 HTTP 请求。在入门阶段先掌握接收请求并返回响应即可主动发起请求会在后续 working_with_apis.md 等课程中进一步深化。从回调到路由分发回调函数中的req.url可以用来区分不同路径从而分发到不同页面。这正是本课程末尾项目Basic Informational Site的核心逻辑访问/返回index.html访问/about返回about.html访问/contact-me返回contact-me.html其他所有路径返回404.html。不过仅靠http模块手写路由会比较啰嗦这也是后续引入 Express 框架的原因详见 introduction_to_express.md 中对请求的旅程和中间件机制的讲解。入门阶段先用原生http模块亲手实现一遍才能深刻理解框架替你做了什么。文件系统模块读写文件服务端程序离不开文件操作Node 的fsFile System模块正是为此而生。它是 Node 中重度使用的模块之一覆盖文件的读取、创建、更新和删除。写入文件写入文件最常用的方法是fs.writeFile。注意fs模块的大多数方法都同时提供异步回调风格与同步带Sync后缀两种版本异步版本不会阻塞事件循环const fs require(fs); // 异步写入文件不存在则创建存在则覆盖 fs.writeFile(message.txt, Hello Node!, (err) { if (err) throw err; console.log(文件已写入); });对应地fs.appendFile可以在已有文件末尾追加内容适合日志类场景fs.rename用于重命名文件fs.unlink用于删除文件。它们共同构成了原文所说的读取、创建、更新和删除四类操作// 追加内容创建/更新 fs.appendFile(message.txt, \nSecond line, (err) { if (err) throw err; }); // 重命名更新 fs.rename(message.txt, renamed.txt, (err) { if (err) throw err; }); // 删除 fs.unlink(renamed.txt, (err) { if (err) throw err; });读取文件读取文件使用fs.readFile回调的第二个参数即为文件内容const fs require(fs); fs.readFile(message.txt, utf8, (err, data) { if (err) { console.error(err); return; } console.log(data); });传入utf8编码参数后data就是可直接使用的字符串省略该参数时data会是 Buffer二进制缓冲区。在 Basic Informational Site 项目中fs.readFile正是按 URL 读取对应 HTML 文件并返回给客户端的关键手段。URL 类解析网址为可读部分处理网络请求时经常需要把网址拆解为协议、主机名、路径、查询参数等可读部分。Node 的url模块提供 WHATWG 标准的URL类来完成这项工作const myURL new URL(https://example.org:8080/path/to/page?nameferretage3); console.log(myURL.hostname); // example.org console.log(myURL.port); // 8080 console.log(myURL.pathname); // /path/to/page console.log(myURL.search); // ?nameferretage3 console.log(myURL.searchParams.get(name)); // ferretURL实例暴露了hostname、port、pathname、search、searchParams等大量只读属性searchParams还提供了get、set、append、delete等方法方便读写查询参数。原文建议亲手运行这些代码示例看看它是如何工作的因为这正是把请求的 URL映射到要返回的页面文件这一路由逻辑的数据基础。Events 模块创建、触发与监听事件Node 是事件驱动的而事件机制的底层实现就是events模块中的EventEmitter事件发射器类。你可以创建自己的事件发射器用on或addListener注册监听器用emit触发事件const EventEmitter require(events); const myEmitter new EventEmitter(); // 监听 greet 事件 myEmitter.on(greet, (name) { console.log(Hello, ${name}!); }); // 触发 greet 事件并携带参数 myEmitter.emit(greet, Node);事件发射器可以同时注册多个监听器事件触发时它们会按注册顺序依次执行emit传入的额外参数会被透传给监听器函数。理解EventEmitter之后你会发现自己写的 HTTP 服务器本质上也是一个在收到请求时触发回调的事件机制——http.createServer的回调、fs.readFile的回调都是事件驱动模型的具体体现。NPM 与 package.jsonNPMNode Package Manager随 Node 一同安装是 Node 生态的包管理工具用于安装、管理和发布第三方依赖。入门阶段需要掌握三个基本命令# 初始化项目生成 package.json npm init -y # 安装依赖-D 表示作为开发依赖 npm install package-name npm install -D package-name # 运行 package.json scripts 中定义的脚本 npm run script-namepackage.json是项目的身份档案记录项目名称、版本、脚本和依赖。本仓库根目录的 package.json 就是一个典型实例其中定义了lint、fix、test三个 npm script并通过devDependencies引入markdownlint-cli2作为开发依赖{ name: curriculum, version: 1.0.0, scripts: { lint: markdownlint-cli2, fix: markdownlint-cli2 --fix, test: node --test }, license: CC BY-NC-SA 4.0, devDependencies: { markdownlint-cli2: ^0.23.2 } }这个文件展示了三个可迁移到任何 Node 项目的实践用scripts固化常用命令、用devDependencies区分仅开发期需要的工具、用语义化版本范围^0.23.2声明依赖版本。在 introduction_to_express.md 中Express 的安装也正是通过npm init -y加npm install express完成的可见 NPM 是后续所有第三方框架学习的前提。实战演练Basic Informational Site 项目学习完上述模块后就到了动手环节。本课程末尾的项目 project_basic_informational_site.md 要求用 Node 创建一个包含 4 个页面的基础信息站点。项目规格如下在项目目录中创建 4 个 HTML 文件index.htmlabout.htmlcontact-me.html404.html创建 Node 服务器文件index.js编写代码根据 URL 返回对应页面http://localhost:8080→ 返回index.htmlhttp://localhost:8080/about→ 返回about.htmlhttp://localhost:8080/contact-me→ 返回contact-me.html访问上述以外的任何路径 → 返回404.html结合本篇所学一个可行的实现骨架是用http.createServer接收请求读取req.url判断路径再用fs.readFile读取对应的 HTML 文件并通过res返回路径不匹配时回退到404.html同时通过res.writeHead设置Content-Type: text/html和合适的 HTTP 状态码。项目刻意强调页面内容并不重要不需要花时间美化目的是把全部注意力放在 Node 的服务端逻辑上。完成这个项目后如果你觉得手写路由和文件分发比较繁琐可以对照 introduction_to_express.md 的作业要求安装 Express 用几个app.get()重写一遍同样的项目——这将是理解框架为什么存在的最佳对比实验。进阶补充环境变量与调试入门之后还有两个与 Node 日常开发强相关的能力值得一并掌握。用环境变量隔离配置environment_variables.md 介绍了如何让不同环境本机开发、云端部署使用不同的配置。环境变量可以通过以下方式加载直接在启动命令中赋值NODE_ENVprod node index.js使用 shell 的export命令写入当前会话使用.env文件Node 内置支持通过node --env-file.env index.js或process.loadEnvFile()加载使用 dotenv 等第三方库老项目中常见。在代码中通过process.env读取例如const PORT process.env.PORT || 3000;注意环境变量的值永远是字符串需要数值或布尔时须自行转换包含敏感信息的.env文件必须加入.gitignore绝不可提交到仓库。用调试器定位问题debugging_node.md 则强调服务端代码不能依赖浏览器 DevTools而应学会使用 VS Code 内置的 Node 调试器在编辑器中直接打断点、观察变量。VS Code 的 JavaScript Debug Terminal 是最便捷的启动方式之一这是从会写 Node走向能调好 Node的关键工具。知识自检读完本篇后试着回答以下问题对应原文档的 Knowledge check什么是文件系统模块你会如何使用它、为什么使用它如何在终端中运行一个 Node.js 脚本http.createServer的回调函数在什么时机被执行如何用fs模块读取和写入文件用URL类如何拿到网址的路径和查询参数如何创建自己的EventEmitter并监听、触发事件为什么说 Node 是异步事件驱动的运行时如果这些问题都能清晰作答并且能独立完成 Basic Informational Site 项目你就已经跨过了 Node.js 入门的门槛可以带着对回调、模块、事件和文件操作的理解进入 Express 与更复杂的后端开发学习了。【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考