DEV Community

Matheus Alves
Matheus Alves

Posted on • Edited on • Originally published at hackernoon.com

What’s the Difference Between path.join() and path.resolve()?

How many times have you come across path.join() and path.resolve() in Node.js projects without really understanding the difference between them?

In my own experience, I’ve seen different projects with the same structure using one over the other and I couldn’t really understand why. After becoming aware of my lack of knowledge, I decided to investigate and share my learnings with you.

Table of Contents

List of Important Terms

I believe once you understand the terms listed below it will be easier for you to grasp the differences between the two methods.

  1. String: A string is a sequence of characters that are interpreted literally (the exact way it has been written) by a script, e.g., "this is a string". They must be surrounded by quotation marks if there’s more than one word.

  2. Path: A path is simply a string that identifies the location of a file or directory on a computer, e.g., "/home/user/Documents/file.ext" or "/home/user/Downloads/". I’m going to use the word ‘file’ here for referring to both files and directories.

  3. Relative path: A relative path is a string that identifies the location of a file relative to the location of another file.

    For instance, let’s assume some user has the following directory structure:

    Directory structure example
    Directory structure example

    If Downloads is the current working directory (CWD) and the user wants to access a file inside the Documents directory, he would have to navigate up one level, and then go down into the Documents directory. Something like this on POSIX-compliant systems (Linux, MacOS, etc.) cd ../Documents/file.ext or like this on Windows cd ..\Documents\file.ext.

    Note: On the terminal or prompt we don’t need to surround the string with quotation marks if there are no spaces in the names of the files. Trying to execute cd ../Documents/my file.ext would result in an error message.

  4. Absolute path: Simplifying, an absolute path is the string that identifies the location of a file relative to the root of the system. For example, instead of trying to access the file from the previous example via a relative path, the user could’ve specified an absolute path like this cd /home/user/Documents/file.ext. We can specify an absolute path from any location.

  5. Path segment: A path segment is a slice of the path. For example, we have /home, /user and /Documents as segments of /home/user/Documents/file.ext.

  6. __dirname: This is a Node.js environment variable that specifies the absolute path for the directory which contains the currently executing file.

For instance, if you have webpack.config.js:

console.log(__dirname)
Enter fullscreen mode Exit fullscreen mode

The expected output on the console would be

/home/user/Documents/project
Enter fullscreen mode Exit fullscreen mode

If the webpack.config.js is inside the project directory.

In other words, __dirname is simply the string of the absolute path to the file’s location.

  1. Path normalization: As you saw, there are differences between the strings used to specify the path on different OSs. Windows uses \ while POSIX-compliant OSs use / as a directory separator, just for instance. Path normalization happens when the string is modified so that it conforms to a valid path on the target operating system. If you want to learn more about the steps required to perform path normalization, see https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats.

Brief Recap - How to Change Directories on Terminal/Prompt

. and ./ represent the CWD;

.. and ../ represent the parent of the CWD;

/ represents the root directory

If you put cd in front of them, they’ll take you to the desired location.

I said it was going to be brief 😂

What does path.join() do?

The path.join() method joins all given path segments together using the platform-specific separator as a delimiter, then normalizes the resulting path.

The syntax is quite simple: path.join(…paths), where …paths is a sequence of segments.

For example, calling path.join("path", "/to", "some", "file") returns the following string path/to/some/file in a POSIX-compliant system.

If you don’t understand what the mean, take a look at Spread syntax (...).

What does path.resolve() do?

The path.resolve() method resolves a sequence of paths or path segments into an absolute path.

Almost identical syntax: path.resolve(…paths). This method processes the paths from right to left and when it finds a / treats it as the root of the system.

For example, calling path.resolve(__dirname, "/path") would return /path, because the second argument has a leading / and thus will be treated as the root of the system.

The key difference

path.join() simply concatenates segments and its return may or may not result in an absolute path. path.resolve() always returns an absolute path, using the target operating system’s root as the root or the first argument with a leading / as the new root.

When should you choose one over the other?

It depends. Does your tool require an absolute path? Then use path.resolve(). Do you only need to concatenate segments of paths? Use path.join().

In practice, I can’t remember seeing path.join() or path.resolve() being used without __dirname, which makes both methods result in an absolute path with the OS’s root being the root.

Again, calling path.resolve(__dirname, "/path") makes no sense since __dirname would be totally ignored because the second argument starts with a /. The following is a valid use case: path.resolve(__dirname, 'dist/assets').

Usage examples

Input:

console.log(path.join(__dirname, "path"));
console.log(path.join(__dirname, "/path"));
console.log(path.join(__dirname, "./path"));
console.log(path.join(__dirname, "../path"));

console.log(path.resolve(__dirname, "path"));
console.log(path.resolve(__dirname, "/path"));
console.log(path.resolve(__dirname, "./path"));
console.log(path.resolve(__dirname, "../path"));
Enter fullscreen mode Exit fullscreen mode

Output:

// path.join()
/home/user/some/other/segments/path
/home/user/some/other/segments/path
/home/user/some/other/segments/path
/home/user/some/other/path

//path.resolve()
/home/user/some/other/segments/path
/path
/home/user/some/other/segments/path
/home/user/some/other/path
Enter fullscreen mode Exit fullscreen mode

As you can see, if what you need is an absolute path to the current executing file, you can choose any of the following:

console.log(path.join(__dirname, "path"));
console.log(path.join(__dirname, "/path"));
console.log(path.join(__dirname, "./path"));
console.log(path.resolve(__dirname, "path"));
console.log(path.resolve(__dirname, "./path"));
Enter fullscreen mode Exit fullscreen mode

I think that’s enough.

If you found this article useful, share it with your friends.

See you next time!

Top comments (0)