Node.js 内置模块 path 专门用于处理文件路径,提供了一系列标准化的工具函数。它可以自动适配 Windows、macOS、Linux 等不同操作系统的路径分隔符差异,安全地完成路径拼接、解析、规范化、提取信息等操作。 结合上一节学习的 fs 文件系统模块,path 模块能彻底解决跨平台路径报错问题,是 Node.js 开发中处理文件的必备工具。
path 是 Node.js 内置核心模块,无需安装,直接导入即可使用,支持两种模块化规范:
// 1. CommonJS 规范(Node.js 默认使用)
const path = require('path');
// 2. ES Module 规范(现代前端推荐)
import path from 'path';在路径操作中,两个全局变量是基础:
__dirname:获取当前文件所在的目录的绝对路径
__filename:获取当前文件的绝对路径
path.join() 是最常用的路径拼接方法,它会根据操作系统自动匹配路径分隔符(Windows \,macOS/Linux /),并规范化路径。
path.join([path1, path2, ...pathN])接收任意个路径片段作为参数
自动处理 ./、../、多余分隔符等异常格式
不会强制生成绝对路径,依赖传入的路径片段
const path = require('path');
// 拼接当前目录 + files 文件夹 + test.txt
const fullPath = path.join(__dirname, 'files', 'test1.txt');
console.log(fullPath);
// 自动解析 ../ 上层目录
const testPath = path.join('/a', '/b/c', '../', 'd');
// 结果:/a/b/d重要规范:所有路径拼接操作,禁止使用
+直接拼接字符串,必须使用path.join(),避免跨平台报错。
path.resolve() 用于将路径片段解析为绝对路径,相当于在命令行中逐层执行 cd 命令。
path.resolve([from ...], to)最终一定返回绝对路径
从右向左拼接参数,直到拼接成绝对路径为止
无参数时,返回当前工作目录
const path = require('path');
// 生成绝对路径
const absolutePath = path.resolve(__dirname, 'test1.txt');
// 对比演示
console.log(path.join('/a', '/b', 'c')); // /a/b/c
console.log(path.resolve('/a', '/b', 'c')); // /b/cpath.normalize() 用于规范化路径,自动解析 ..(上层目录)、.(当前目录),并清理多余的路径分隔符。
path.normalize(path)const path = require('path');
// Windows 系统需转义反斜杠
const rawPath = 'C:\\Users\\Workspaces\\..\\NodeJS\\test1.txt';
const normalizedPath = path.normalize(rawPath);
// 输出:C:\Users\NodeJS\test1.txtpath.basename() 获取路径的最后一部分(文件名),支持过滤文件扩展名。
path.basename(path[, ext])path:必填,目标路径字符串
ext:可选,要剔除的文件扩展名
const path = require('path');
const filePath = path.join(__dirname, 'files', 'test1.txt');
// 带扩展名
console.log(path.basename(filePath)); // test1.txt
// 不带扩展名
console.log(path.basename(filePath, '.txt')); // test1path.dirname() 获取路径中的目录部分(不包含文件名)。
path.dirname(path)const path = require('path');
const filePath = path.join(__dirname, 'files', 'test1.txt');
// 获取文件所在目录
console.log(path.dirname(filePath)); path.extname() 获取路径中的文件扩展名(包含 .)。
path.extname(path)const path = require('path');
const filePath = path.join(__dirname, 'files', 'test1.txt');
console.log(path.extname(filePath)); // .txtpath.isAbsolute() 判断一个路径是否为绝对路径,返回布尔值。
path.isAbsolute(path)const path = require('path');
// 绝对路径
console.log(path.isAbsolute('/files/test1.txt')); // true
// 相对路径
console.log(path.isAbsolute('files/test1.txt')); // false将路径字符串解析为路径对象,包含目录、文件名、扩展名等信息。
const path = require('path');
const info = path.parse('/user/files/test.txt');
/*
{
root: '/',
dir: '/user/files',
base: 'test.txt',
ext: '.txt',
name: 'test'
}
*/将路径对象反向生成路径字符串,与 path.parse 互为逆操作。
path.format({
dir: '/user/files',
base: 'test.txt'
});
// /user/files/test.txtpath.sep:获取系统默认路径分隔符
path.delimiter:获取系统环境变量分隔符
console.log(path.sep); // Windows \ ,macOS /将 HTML 文件中的内联 <style> 和 <script> 内容提取出来,生成独立的 .css 和 .js 文件,实现代码分离。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>时钟</title>
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
background-image: linear-gradient(to bottom right, red, gold);
}
.box {
width: 400px;
height: 250px;
background-color: rgba(255, 255, 255, 0.6);
border-radius: 6px;
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
box-shadow: 1px 1px 10px #fff;
text-shadow: 0px 1px 30px white;
display: flex;
justify-content: space-around;
align-items: center;
font-size: 70px;
user-select: none;
padding: 0 20px;
/* 盒子投影 */
-webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0%, transparent), to(rgba(250, 250, 250, .2)));
}
</style>
</head>
<body>
<div class="box">
<div id="HH">00</div>
<div>:</div>
<div id="mm">00</div>
<div>:</div>
<div id="ss">00</div>
</div>
<script>
window.onload = function () {
// 定时器,每隔 1 秒执行 1 次
setInterval(() => {
var dt = new Date();
var HH = dt.getHours();
var mm = dt.getMinutes();
var ss = dt.getSeconds();
// 为页面上的元素赋值
document.querySelector("#HH").innerHTML = padZero(HH);
document.querySelector("#mm").innerHTML = padZero(mm);
document.querySelector("#ss").innerHTML = padZero(ss);
}, 1000);
};
// 补零函数
function padZero(n) {
return n > 9 ? n : "0" + n;
}
</script>
</body>
</html>读取 assets/clock.html 文件
提取 CSS 样式 → 生成 clock/index.css
提取 JS 代码 → 生成 clock/index.js
生成新的 HTML 文件,引入外部样式和脚本
在项目根目录创建 assets 文件夹,新建 clock.html,写入提供的 HTML 代码。
const fs = require('fs');
const path = require('path');
// 1. 定义文件路径
const htmlPath = path.join(__dirname, 'assets', 'clock.html');
const outputDir = path.join(__dirname, 'clock');
// 2. 正则表达式:匹配 style 和 script 标签(非贪婪匹配)
const regStyle = /<style>[\s\S]*?<\/style>/;
const regScript = /<script>[\s\S]*?<\/script>/;
// 3. 递归创建输出目录(核心修复:避免目录不存在报错)
fs.mkdir(outputDir, { recursive: true }, (err) => {
if (err) throw err;
// 目录创建成功后读取 HTML 文件
readHtmlFile();
});
// 读取 HTML 文件
function readHtmlFile() {
fs.readFile(htmlPath, 'utf8', (err, data) => {
if (err) {
console.error('读取 HTML 文件失败:', err);
return;
}
// 执行分离操作
resolveCSS(data);
resolveJS(data);
resolveHTML(data);
});
}
// 提取并写入 CSS
function resolveCSS(htmlStr) {
const cssContent = regStyle.exec(htmlStr)[0]
.replace('<style>', '')
.replace('</style>', '');
const cssPath = path.join(outputDir, 'index.css');
fs.writeFile(cssPath, cssContent, (err) => {
err ? console.error('CSS 写入失败') : console.log('CSS 写入成功');
});
}
// 提取并写入 JS
function resolveJS(htmlStr) {
const jsContent = regScript.exec(htmlStr)[0]
.replace('<script>', '')
.replace('</script>', '');
const jsPath = path.join(outputDir, 'index.js');
fs.writeFile(jsPath, jsContent, (err) => {
err ? console.error('JS 写入失败') : console.log('JS 写入成功');
});
}
// 生成新的 HTML
function resolveHTML(htmlStr) {
const newHtml = htmlStr
.replace(regStyle, '<link rel="stylesheet" href="./index.css">')
.replace(regScript, '<script src="./index.js"></script>');
const newHtmlPath = path.join(outputDir, 'index.html');
fs.writeFile(newHtmlPath, newHtml, (err) => {
err ? console.error('HTML 写入失败') : console.log('HTML 写入成功');
});
}确保文件结构正确
终端执行命令:
node 文件名.js执行成功后,根目录会生成 clock 文件夹,包含分离后的 3 个文件
fs.writeFile() 只能创建文件,不能自动创建目录,必须提前用 fs.mkdir 创建
重复写入同一文件,新内容会覆盖旧内容
正则表达式使用非贪婪匹配 [\s\S]*?,避免匹配多余内容
所有路径必须使用 path.join 拼接,保证跨平台兼容
路径拼接优先用 path.join,需要绝对路径用 path.resolve
所有文件操作必须搭配 path 模块,杜绝硬编码路径
写入文件前,务必先判断 / 创建目标目录
路径操作必须做错误处理,避免程序崩溃
path 模块会自动根据操作系统切换路径分隔符,这是 Node.js 跨平台开发的核心保障,永远不要手动写死路径分隔符。
直接用 + 拼接路径 → 跨平台报错
未创建目录直接写入文件 → 找不到路径报错
Windows 系统未转义反斜杠 → 路径解析失败
核心作用:path 模块解决跨平台路径问题,是 fs 模块的最佳搭档
高频方法:join(拼接)、resolve(绝对路径)、basename(文件名)、extname(扩展名)
核心规则:路径拼接必用 path.join,写入文件前必创建目录
实战价值:可快速实现文件拆分、路径解析、文件管理等开发需求