paint-brush
What’s the Difference Between path.join() and path.resolve()?by@matheus4lves
11,330 reads
11,330 reads

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

by Matheus AlvesApril 4th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

You can get the absolute path to a file/directory by combining either path.join() or path.resolve() functions with the Node.js __dirname environment variable. When using path.resolve(), the second argument must not have a leading "/" because otherwise it would be considered the root of the OS. If what you need is to concatenate path segments, use path.join() instead.
featured image - What’s the Difference Between path.join() and path.resolve()?
Matheus Alves HackerNoon profile picture

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
  • Brief recap - how to change directories on terminal/prompt
  • What does path.join() do?
  • What does path.resolve() do?
  • The key difference
  • When should you choose one over the other?
  • Usage examples

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


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.


  1. 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.


  2. 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.


  3. __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)


The expected output on the console would be

/home/user/Documents/project


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 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/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 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

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"));

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


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"));


I think that’s enough.

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

See you next time!