一、 Node.js 模块化系统 (Module System)
Node.js 采用了模块化系统,允许你将程序拆分为多个独立、可复用的文件(模块)。这使得代码更易于维护、组织和共享。
1. 模块加载优先级
当使用 require()
加载一个模块时,Node.js 会按照以下顺序查找:
-
内置模块 (Built-in Modules) :如
http
,fs
,path
等。这些是 Node.js 官方提供的核心模块,拥有最高优先级。 -
文件模块 (File Modules) :
- 以
./
或../
开头的相对路径。 - 以
/
开头的绝对路径。
- 以
-
第三方模块 (Third-party Modules) :
- 不带路径标识的模块名,如
require('express')
。 - Node.js 会在当前目录的
node_modules
文件夹中查找,如果找不到,会逐级向上层目录的node_modules
文件夹中查找,直到根目录。
- 不带路径标识的模块名,如
2. 自定义模块
- 执行机制 :当你
require()
一个自定义模块时,该模块中的代码会立即被执行一次。 - 缓存机制 :Node.js 会对第一次加载的模块进行缓存。后续再次
require()
同一个模块时,不会重新执行模块代码,而是直接从缓存中获取导出的对象。这确保了模块的单例性并提高了性能。
3. 第三方模块
- 通过包管理工具 npm (Node Package Manager) 或 yarn 进行安装和管理。
- 安装后会存放在项目的
node_modules
目录下。 - 例如 Express 框架,它是一个基于 Node.js 内置
http
模块封装的、功能更强大的第三方 Web 开发框架。
二、 核心内置模块详解
1. path
模块:路径处理
path
模块提供了一系列工具函数,用于处理和转换文件路径字符串,它能够很好地处理不同操作系统(如 Windows 和 Linux/macOS)之间的路径差异。
-
引入模块:
javascript
iniconst path = require('path');
-
核心方法:
path.join([...paths])
- 功能 :用于将多个路径片段拼接成一个规范化的路径字符串。它会自动使用特定于平台的路径分隔符(Windows 是 ``,POSIX 是
/
)。 __dirname
:这是一个 Node.js 内置的全局变量,它返回当前执行脚本所在目录的绝对路径 。在进行文件操作时,使用__dirname
拼接路径可以确保路径的正确性,避免因运行目录不同而导致的问题。
- 功能 :用于将多个路径片段拼接成一个规范化的路径字符串。它会自动使用特定于平台的路径分隔符(Windows 是 ``,POSIX 是
-
代码示例:
javascript
javascriptconst path = require('path'); // __dirname 代表当前文件(例如 a.js)所在的目录 // 假设 a.js 在 /Users/test/project/ 目录下 // __dirname 的值就是 '/Users/test/project' // 拼接路径: // './package.json' 是相对路径 // '/b' 会被当做一个路径片段 // '../' 会返回上一级目录,抵消掉前面的 '/b' const finalPath = path.join(__dirname, './package.json', '/b', '../'); // 输出结果 (在 POSIX 系统上): /Users/test/project/package.json console.log(finalPath);
2. fs
模块:文件系统 (File System)
fs
模块用于对本地文件系统进行操作,例如读取文件、写入文件、创建目录等。操作分为同步和异步两种方式,推荐使用异步方式以避免阻塞主线程。
-
引入模块:
javascript
iniconst fs = require('fs');
-
核心方法 1:
fs.readFile(path, [options], callback)
- 读取文件-
功能:异步地读取一个文件的全部内容。
-
参数:
-
path
: 必填,文件的路径。 -
[options]
: 可选,通常是一个对象或字符串,用于指定编码,如'utf8'
。如果未指定编码,则返回原始的 Buffer 数据。 -
callback
: 必填,文件读取完成后执行的回调函数,格式为function(err, data)
。err
: 如果读取出错,它是一个错误对象;如果成功,则为null
。data
: 读取到的文件内容(字符串或 Buffer)。
-
-
-
代码示例(读取文件) :
javascript
javascriptconst fs = require('fs'); const path = require('path'); const filePath = path.join(__dirname, './package.json'); fs.readFile(filePath, 'utf8', function(err, data) { // 错误优先的回调模式:首先判断错误对象是否存在 if (err) { return console.log("读取文件失败!错误详情:", err); } console.log("读取文件成功!内容如下:\n", data); });
-
核心方法 2:
fs.writeFile(file, data, [options], callback)
- 写入文件-
功能 :异步地将数据写入一个文件。如果文件已存在,默认会覆盖原有内容。如果文件不存在,则会创建新文件。
-
参数:
file
: 必填,要写入的文件路径。data
: 必填,要写入的数据,通常是字符串或 Buffer。[options]
: 可选,指定编码,默认为'utf8'
。callback
: 必填,写入完成后执行的回调函数,格式为function(err)
。
-
-
代码示例(写入文件) :
javascript
javascriptconst fs = require('fs'); const contentToWrite = '这是通过 fs.writeFile 写入的新内容。'; fs.writeFile('./my-new-file.txt', contentToWrite, 'utf8', function(err) { if (err) { return console.log("写入文件失败!错误信息:", err.message); } console.log("写入文件成功!"); });
3. http
模块:创建 Web 服务器
http
模块是 Node.js 的核心功能之一,用于构建 HTTP 服务器和客户端。
-
引入模块:
javascript
iniconst http = require('http');
-
常用 IP 和端口:
127.0.0.1
是回环地址,等同于localhost
,指向本机。- HTTP 服务的默认端口是
80
,如果服务器监听的是80
端口,访问时可以省略端口号(例如http://localhost
)。
-
创建服务器的步骤:
-
创建服务器实例 :
const server = http.createServer();
-
监听请求事件 :
server.on('request', (req, res) => { ... });
- 只要有客户端请求到达服务器,就会触发
request
事件,并执行回调函数。 req
(Request): 请求对象,包含了客户端发来的所有信息,如请求 URL (req.url
)、请求方法 (req.method
)、请求头等。res
(Response): 响应对象,用于向客户端发送响应信息。
- 只要有客户端请求到达服务器,就会触发
-
启动服务器 :
server.listen(port, [hostname], [callback]);
- 让服务器在指定的端口(
port
)和主机名(hostname
)上开始监听客户端请求。
- 让服务器在指定的端口(
-
-
代码示例(一个简单的 Web 服务器) :
javascript
iniconst http = require('http'); // 1. 定义主机名和端口 const hostname = '127.0.0.1'; const port = 3000; // 2. 创建服务器实例 const server = http.createServer(); // 3. 监听 request 事件,处理客户端请求 server.on("request", (req, res) => { // 打印客户端的请求信息 console.log(`收到客户端请求:地址=${req.url}, 方法=${req.method}`); // 根据不同的请求 URL,返回不同的内容(简单的路由) const url = req.url; let content = `<h1>404 Not Found!</h1>`; // 默认内容 if (url === '/' || url === '/index.html') { content = `<h1>欢迎来到首页</h1>`; } else if (url === '/about.html') { content = `<h1>关于我们页面</h1>`; } // 设置响应头,解决中文乱码问题 // 'Content-Type' 告诉浏览器响应内容的类型和编码 res.setHeader('Content-Type', 'text/html; charset=utf-8'); // 设置 HTTP 状态码 res.statusCode = 200; // 发送响应内容给客户端,并结束本次响应 res.end(content); }); // 4. 启动服务器,并监听指定端口 server.listen(port, hostname, () => { console.log(`服务器已启动,正在 http://${hostname}:${port}/ 上运行`); });