Node.js: Path and URL Modules

Last updated: 2026-08-26

1. The Story: A Deployment Disaster Caused by a Delimiter

The CLI tool developed by Bob tested perfectly on macOS—path concatenation used /, and both reading the configuration and writing logs worked without issues. However, after deploying it to a Linux server, the program immediately reported an error: ENOENT: no such file or directory. Upon investigation, it was discovered that Bob had hard-coded / as the path separator in the code, while certain path-handling logic on Windows used \, leading to confusion in path parsing. This incident gave Bob a deep understanding of the purpose of the path module—never manually concatenate paths.

(1) You will learn



2. Core Methods of the path Module

The path module is a built-in Node.js module that provides tools for concatenating, parsing, and formatting file paths, automatically handling differences in path separators across operating systems.

(1) path.join — Path concatenation

path.join() Concatenates multiple path segments into a single standardized path, automatically using the current system's separator.

▶ Example: Basic Path Concatenation with path.join

JAVASCRIPT
const path = require('path');

const fullPath = path.join('/app', 'src', 'utils', 'helper.js');
console.log(fullPath);
// macOS/Linux: /app/src/utils/helper.js
// Windows:     \app\src\utils\helper.js
▶ Try it Yourself

▶ Example: path.join Automatic Normalization

JAVASCRIPT
const path = require('path');

console.log(path.join('/app', '../config', 'settings.json'));
// /config/settings.json

console.log(path.join('src', '.', 'index.js'));
// src/index.js
▶ Try it Yourself

(2) path.resolve — Resolve to an absolute path

path.resolve() Concatenate paths from right to left until an absolute path is obtained. If an absolute path is not obtained, use the current working directory as the base.

▶ Example: Basic Usage of path.resolve

JAVASCRIPT
const path = require('path');

console.log(path.resolve('src', 'index.js'));
// /current/working/dir/src/index.js

console.log(path.resolve('/app', 'src', 'index.js'));
// /app/src/index.js

console.log(path.resolve('/app', '/tmp', 'file.txt'));
// /tmp/file.txt(Use the absolute path on the far right as the reference.)
▶ Try it Yourself

(3) path.parse and path.format — Path Parsing and Reconstruction

path.parse() breaks the path down into five parts: root, dir, base, ext, and name; path.format() reassembles the object into a path string.

▶ Example: parse the path using path.parse

JAVASCRIPT
const path = require('path');

const parsed = path.parse('/app/src/utils/helper.js');
console.log(parsed);
▶ Try it Yourself
TEXT 📖 Display only
{
  root: '/',
  dir: '/app/src/utils',
  base: 'helper.js',
  ext: '.js',
  name: 'helper'
}
100%
graph LR
    A["/app/src/utils/helper.js"] --> B["root: /"]
    A --> C["dir: /app/src/utils"]
    A --> D["base: helper.js"]
    D --> E["name: helper"]
    D --> F["ext: .js"]
    style A fill:#4CAF50,color:#fff
    style B fill:#FF9800,color:#fff
    style C fill:#2196F3,color:#fff
    style D fill:#9C27B0,color:#fff
    style E fill:#E91E63,color:#fff
    style F fill:#FF5722,color:#fff

▶ Example: path.format—Rewriting Paths

JAVASCRIPT
const path = require('path');

const filePath = path.format({
  dir: '/app/src/utils',
  base: 'helper.js'
});
console.log(filePath);
// /app/src/utils/helper.js
▶ Try it Yourself

(4) path.extname / path.basename / path.dirname

These three methods extract the file extension, the filename, and the directory portion of the path, respectively.

▶ Example: Extracting the parts of a path

JAVASCRIPT
const path = require('path');

const filePath = '/app/src/utils/helper.js';

console.log(path.extname(filePath));   // .js
console.log(path.basename(filePath));  // helper.js
console.log(path.basename(filePath, '.js')); // helper
console.log(path.dirname(filePath));   // /app/src/utils
▶ Try it Yourself

3. Cross-Platform Path Constants

Path separators and environment variable separators vary across operating systems; the path module provides constants to accommodate these differences.

(1) path.sep — Path separator

Platform path.sep
macOS / Linux /
Windows \

(2) path.delimiter — Environment variable separator

Platform path.delimiter
macOS / Linux :
Windows ;

▶ Example: Using path.sep and path.delimiter

JAVASCRIPT
const path = require('path');

console.log('Delimiter:', JSON.stringify(path.sep));
// macOS/Linux: "/"
// Windows:     "\\"

const envPaths = process.env.PATH.split(path.delimiter);
console.log('PATH Number of entries:', envPaths.length);
▶ Try it Yourself

4. The url Module and the URL Constructor

(1) url.parse (deprecated) vs new URL()

url.parse() is an older version of the API and has been marked as deprecated. We recommend using the new URL() constructor, which conforms to the WHATWG standard.

Feature url.parse() new URL()
Standard Legacy Node.js WHATWG Standard
Status Deprecated Recommended
Error Handling Silently return null Throw a TypeError
searchParams None Built-in URLSearchParams
Performance Slower Faster
JAVASCRIPT
const url = require('url');

const parsed = url.parse('https://example.com/api/users?name=Bob&page=1');
console.log(parsed.hostname);
console.log(parsed.query);
▶ Try it Yourself
TEXT 📖 Display only
example.com
name=Bob&page=1
JAVASCRIPT
const myUrl = new URL('https://example.com/api/users?name=Bob&page=1');

console.log(myUrl.hostname);
console.log(myUrl.pathname);
console.log(myUrl.searchParams.get('name'));
console.log(myUrl.searchParams.get('page'));
▶ Try it Yourself
TEXT 📖 Display only
example.com
/api/users
Bob
1

(2) url.searchParams —— Manipulating query parameters

The URL object's searchParams property is an instance of URLSearchParams, which provides convenient methods for adding, deleting, updating, and querying parameters.

▶ Example: CRUD Operations for searchParams

JAVASCRIPT
const myUrl = new URL('https://example.com/search');
myUrl.searchParams.set('q', 'nodejs');
myUrl.searchParams.set('lang', 'zh');
myUrl.searchParams.append('tag', 'backend');
myUrl.searchParams.append('tag', 'tutorial');
myUrl.searchParams.delete('lang');

console.log(myUrl.toString());
// https://example.com/search?q=nodejs&tag=backend&tag=tutorial

console.log(myUrl.searchParams.getAll('tag'));
// [ 'backend', 'tutorial' ]
▶ Try it Yourself

(3) url.fileURLToPath — Converts a file URL to a local path

In the ESM module, import.meta.url returns a URL in the file:// format, which must be converted to a file system path using url.fileURLToPath().

▶ Example: fileURLToPath Conversion

JAVASCRIPT
const { fileURLToPath } = require('url');

const fileUrl = 'file:///app/src/index.js';
const filePath = fileURLToPath(fileUrl);
console.log(filePath);
// macOS/Linux: /app/src/index.js
// Windows:     \app\src\index.js
▶ Try it Yourself

5. __dirname / __filename vs import.meta.url

This is the key difference between the CJS and ESM module systems when it comes to obtaining the current file path.

Feature __dirname / __filename import.meta.url
Module System CJS (require) ESM (import)
Return Type Absolute Path String file:// URL String
Availability Global variable, use directly Requires fileURLToPath
Directory path __dirname (retrieve directly) Requires dirname(fileURLToPath())
File Path __filename (direct access) Requires conversion using fileURLToPath()

▶ Example: Using __dirname in CJS

JAVASCRIPT
const path = require('path');

console.log('__dirname:', __dirname);
console.log('__filename:', __filename);

const configPath = path.join(__dirname, 'config', 'settings.json');
console.log(configPath);
▶ Try it Yourself

▶ Example: Using import.meta.url in ESM

JAVASCRIPT
import { fileURLToPath } from 'url';
import path from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

console.log('__dirname:', __dirname);
console.log('__filename:', __filename);
▶ Try it Yourself

6. Quick Reference Table of Common Path Methods

Method Parameters Return Value Purpose
path.join() ...paths string Concatenate path segments and automatically normalize them
path.resolve() ...paths string Resolve to absolute path
path.parse() pathString object Break down the path into its constituent parts
path.format() pathObject string Reconstruct the path object as a string
path.extname() pathString string Get File Extension
path.basename() pathString[, ext] string Get filename (extension can be omitted)
path.dirname() pathString string Go to the Table of Contents
path.isAbsolute() pathString boolean Check if it is an absolute path
path.normalize() pathString string Normalized path (handling .., .)
path.relative() from, to string Get the relative path from "from" to "to"


7. Best Practices for Cross-Platform Path Handling

(1) Core Principles

Rule Description Incorrect Example Correct Example
Using path.join Automatic delimiter handling 'src' + '/' + 'index.js' path.join('src', 'index.js')
Use path.sep Quote separator constant str.split('/') str.split(path.sep)
Use path.resolve Get the absolute path process.cwd() + '/' + file path.resolve(file)
Use fileURLToPath Convert file URL import.meta.url.slice(7) fileURLToPath(import.meta.url)
Avoid __dirname in ESM Not available Use __dirname directly Use import.meta.url instead

▶ Example: (2) Common Error Patterns

JAVASCRIPT
const path = require('path');

// ❌ Hard-coded delimiters
const bad1 = '/app/data/' + 'config.json';

// ✅ Usage path.join
const good1 = path.join('/app', 'data', 'config.json');

// ❌ Manually Merge Working Directories
const bad2 = process.cwd() + '/output/result.log';

// ✅ Usage path.resolve
const good2 = path.resolve('output', 'result.log');

// ❌ String Replacement Delimiter
const bad3 = somePath.replace(/\\/g, '/');

// ✅ Usage path.normalize
const good3 = path.normalize(somePath);
▶ Try it Yourself

8. Comprehensive Example: Cross-Platform File Path Tool

The following example simulates the core logic of Bob’s revised CLI tool: reading the configuration path, constructing the data directory, parsing the URL, and extracting parameters.

JAVASCRIPT
const path = require('path');
const { fileURLToPath } = require('url');

class PathTool {
  constructor(baseDir) {
    this.baseDir = baseDir || process.cwd();
  }

  resolveConfigPath(configRelativePath) {
    return path.resolve(this.baseDir, configRelativePath);
  }

  buildDataPath(...segments) {
    return path.join(this.baseDir, 'data', ...segments);
  }

  parseUrl(urlString) {
    const myUrl = new URL(urlString);
    return {
      protocol: myUrl.protocol,
      hostname: myUrl.hostname,
      pathname: myUrl.pathname,
      params: Object.fromEntries(myUrl.searchParams.entries())
    };
  }

  extractFileInfo(filePath) {
    const parsed = path.parse(filePath);
    return {
      directory: parsed.dir,
      fileName: parsed.name,
      extension: parsed.ext,
      fullPath: filePath
    };
  }

  toFilePath(urlOrPath) {
    if (urlOrPath.startsWith('file://')) {
      return fileURLToPath(urlOrPath);
    }
    return path.resolve(urlOrPath);
  }
}

const tool = new PathTool('/app/project');

// 1. Parsing the Configuration Path
const configPath = tool.resolveConfigPath('config/app.json');
console.log('Configuration Path:', configPath);
// /app/project/config/app.json

// 2. Data Merge Catalog
const dataPath = tool.buildDataPath('users', 'profiles.json');
console.log('Data Path:', dataPath);
// /app/project/data/users/profiles.json

// 3. Analysis URL and extract the parameters
const parsed = tool.parseUrl('https://api.example.com/v1/users?role=admin&active=true');
console.log('URL Analysis:', parsed);
// { protocol: 'https:', hostname: 'api.example.com',
//   pathname: '/v1/users', params: { role: 'admin', active: 'true' } }

// 4. Extract File Information
const info = tool.extractFileInfo('/app/project/data/users/profiles.json');
console.log('File Information:', info);
// { directory: '/app/project/data/users',
//   fileName: 'profiles', extension: '.json', fullPath: '...' }

// 5. file URL File Path
const localPath = tool.toFilePath('file:///app/project/config/app.json');
console.log('Local Path:', localPath);
// /app/project/config/app.json

❓ FAQ

Q What is the difference between path.join and path.resolve?
A path.join simply concatenates path segments and normalizes them; it does not guarantee that the result is an absolute path. path.resolve resolves the path from right to left until an absolute path is produced; if no absolute path is encountered, it uses process.cwd() as the base.
Q Why use path.join instead of string concatenation?
A path.join automatically uses the current system’s path separator, handles the normalization of .. and ., and avoids cross-platform compatibility issues caused by hard-coding / or \.
Q Can __dirname be used in ESM?
A No. The __dirname and __filename global variables do not exist in ESM modules; you need to use path.dirname(fileURLToPath(import.meta.url)) to obtain equivalent values.
Q Has url.parse been deprecated?
A Yes, url.parse has been marked as deprecated. We recommend using the new URL() constructor from the WHATWG standard, which offers better error handling and built-in support for searchParams.
Q How can I ensure path compatibility between Windows and macOS/Linux?
A Always use path.join or path.resolve to concatenate paths, use path.sep to specify the separator, use path.delimiter to handle environment variables, and avoid any hard-coded separator strings.
Q What does import.meta.url return?
A It returns the file:// protocol URL string for the current module (e.g., file:///app/src/index.js), which must be converted to a filesystem path using fileURLToPath().
Q Does path.isAbsolute behave consistently across different platforms?
A No, it does not. On POSIX systems, /usr/local is an absolute path, while on Windows, C:\Users is an absolute path and /usr/local is not. path.isAbsolute determines the result based on the current platform.

📖 Summary


📝 Exercises

  1. Complete all the code examples in this lesson and make sure each one runs correctly.
  2. Modify the comprehensive example and add your own extensions
  3. Review the official documentation, identify 1–2 APIs not covered in this lesson, and write test code for them.
  4. Reflection: How would you apply what you’ve learned in this lesson to a real-world project?
  5. Try to combine what you’ve learned in this lesson with material from previous lessons to build a small project.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏