How many times have you come across and in Node.js projects without really understanding the difference between them? path.join() path.resolve() 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. A string is a sequence of characters that are interpreted literally (the exact way it has been written) by a script, e.g., . They must be surrounded by quotation marks if there’s more than one word. String: "this is a string" A path is simply a that identifies the location of a or on a computer, e.g., or . I’m going to use the word ‘file’ here for referring to both and Path: string file directory "/home/user/Documents/file.ext" "/home/user/Downloads/" files directories. A relative path is a that identifies the location of a file relative to the location of another file. Relative path: string For instance, let’s assume some user has the following directory structure: 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.) or like this on Windows . cd ../Documents/file.ext cd ..\Documents\file.ext 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 would result in an error message. Note: cd ../Documents/my file.ext Simplifying, an absolute path is the 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 . We can specify an absolute path from any location. Absolute path: string cd /home/user/Documents/file.ext A path segment is a slice of the path. For example, we have , and as segments of . Path segment: /home /user /Documents /home/user/Documents/file.ext This is a Node.js environment variable that specifies the for the which contains the currently executing __dirname: absolute path directory 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 is inside the directory. webpack.config.js project In other words, __dirname is simply the of the absolute path to the file’s location. string As you saw, there are differences between the 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 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 . Path normalization: strings \ / string 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 in front of them, they’ll take you to the desired location. cd I said it was going to be brief 😂 What does path.join() do? The method joins all given segments together using the platform-specific separator as a delimiter, then normalizes the resulting path. path.join() path The syntax is quite simple: , where is a sequence of . path.join(…paths) …paths segments For example, calling returns the following string in a POSIX-compliant system. path.join("path", "/to", "some", "file") path/to/some/file 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 method resolves a sequence of paths or path segments into an absolute path. path.resolve() Almost identical syntax: . This method processes the paths and when it finds a treats it as the root of the system. path.resolve(…paths) from right to left / For example, calling would return , because the second argument has a leading and thus will be treated as the root of the system. path.resolve(__dirname, "/path") /path / The key difference simply concatenates segments and its return result in an absolute path. returns an absolute path, using the target operating system’s root as the root or first argument with a leading as the new root. path.join() may or may not path.resolve() always / When should you choose one over the other? It depends. Does your tool require an path? Then use . Do you only need to concatenate segments of paths? Use . absolute path.resolve() path.join() In practice, I can’t remember seeing or being used without , which makes both methods result in an absolute path with the OS’s root being the root. path.join() path.resolve() __dirname Again, calling makes no sense since would be totally ignored because the second argument starts with a . The following is a valid use case: . path.resolve(__dirname, "/path") __dirname / 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 path to the current executing file, you can choose any of the following: absolute 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!