This is the 18th day of my participation in the August Challenge
The Node.js path module is a built-in module that helps you use file system paths in an operating system independent manner. The Path module is essential if you are building CLI tools that support OSX, Linux, and Windows.
Even if you’re building a back-end service that runs only on Linux, the Path module still helps avoid edge conditions when manipulating paths.
Below we describe some common patterns for using the PATH module and why you should use the path module instead of manipulating paths into strings.
Use the Path module in Node
The most common method in the path module is path.join(). This method merges one or more path segments into a string, as follows:
const path = require('path')
path.join('/path'.'to'.'test.txt') // '/path/to/test.txt'
Copy the code
You may be wondering why the path.join() method is used instead of string concatenation.
'/path' + '/' + 'to' + '/' + 'test.txt' // '/path/to/test.txt'
['/path'.'to'.'test.txt'].join('/') // '/path/to/test.txt'
Copy the code
There are two main reasons:
- For Windows support. Windows uses a backslash (
\
) instead of forward slashes (/
) as the path separator.path.join()
Will take care of the problem for us. becausepath.join('data', 'test.txt')
Returns on Linux and OSX as well as Windows'data/test.txt'
. - Used to handle edge cases. When using file system paths, many edge cases pop up. For example, if you try to manually connect two paths, you might accidentally get duplicate path separators.
path.join()
Method we handle the leading and ending slashes as follows:
path.join('data'.'test.txt') // 'data/test.txt'
path.join('data'.'/test.txt') // 'data/test.txt'
path.join('data/'.'test.txt') // 'data/test.txt'
path.join('data/'.'/test.txt') // 'data/test.txt'
Copy the code
Common Path methods
The PATH module also has several methods for extracting path components, such as file extensions or directories.
The path.extName () method returns the file extension as a string:
path.extname('/path/to/test.txt') // '.test'
Copy the code
Just like connecting two paths, getting a file extension is more complicated than it first seems.
If path ends with a., a. Is returned. If the file has no extension and does not end with a., or the file has no extension, a null value is returned.
path.extname('/path/to/index.') / / '. '
path.extname('/path/to/README') / /"
path.extname('/path/to/.gitignore') / /"
Copy the code
The path module also has path.basename() and path.dirname() methods, which get the filename (including the extension) and directory, respectively.
path.basename('/path/to/test.txt') // 'test.txt'
path.dirname('/path/to/test.txt') // '/path/to'
Copy the code
The path.parse() method returns an object that contains paths into five different components, including extensions and directories. The path.parse() method is also a way to get a file name without any extension.
path.parse('/path/to/test.txt')
/* { root: '/', dir: '/path/to', base: 'test.txt', ext: '.txt', name: 'test' } */
Copy the code
usepath.relative()
Methods like path.join() and path.extName () cover most use cases that use file paths. But the path module has several more advanced methods, such as path.relative().
The path.relative(from, to) method returns the relative path from from to based on the current working directory. If from and to are both resolved to the same path (after calling path.resolve(), respectively), a zero-length string is returned.
// Returns the path of the second path relative to the first path
path.relative('/app/views/home.html'.'/app/layout/index.html') / / '.. /.. /layout/index.html'
Copy the code
The path.relative() method is useful if you are given a path relative to one directory, but need a path relative to another. For example, the popular file system monitoring library Chokidar provides a path relative to the monitoring directory.
const watcher = chokidar.watch('mydir')
// If the user adds mydir/path/to/test.txt, mydir/path/to/test.txt will be printed
watcher.on('add'.path= > console.log(path))
Copy the code
This is why the Chokidar tool is used extensively. For example, the common Gatsby or Webpack also makes extensive use of the path.relative() method internally.
For example, Gatsby uses the path.relative() method to help synchronize static file directories.
export const syncStaticDir = (): void= > {
const staticDir = nodePath.join(process.cwd(), `static`)
chokidar
.watch(staticDir)
.on(`add`.path= > {
const relativePath = nodePath.relative(staticDir, path)
fs.copy(path, `${process.cwd()}/public/${relativePath}`)
})
.on(`change`.path= > {
const relativePath = nodePath.relative(staticDir, path)
fs.copy(path, `${process.cwd()}/public/${relativePath}`)})}Copy the code
Now suppose the user adds a new file main.js to the static directory. Chokidar calls the on(‘add’) event handler with the path set to static/main.js. However, when you copy files to /public, you don’t need the extra static/.
Calling path.relative(‘static’, ‘static/main.js’) returns the path of static/main.js relative to static, which is exactly where you want to copy static content to public.
Cross operating system paths and urls
By default, the Path module automatically switches between POSIX (OSX, Linux) and Windows mode depending on the operating system on which the Node process is running.
However, the Path module does work with the Windows Path module on POSIX and vice versa. Posix and path.win32 properties contain the POSIX and Windows versions of the PATH module, respectively.
// return 'path\to\test. TXT ', operating system independent
path.win32.join('path'.'to'.'test.txt')
// Return 'path/to/test.txt', operating system independent
path.posix.join('path'.'to'.'test.txt')
Copy the code
In most cases, automatically switching the PATH module based on the detected operating system is the correct behavior. However, using path.POSIx and path.win32 attributes can be helpful for tests or applications that always want to output Windows or Linux-style paths.
For example, some applications use methods such as path.join() and path.extName () to handle URL paths.
// 'https://api.mydomain.app/api/v2/me'
'https://api.mydomain.app/' + path.join('api'.'v2'.'me')
Copy the code
This approach works for Linux and OSX, but what happens if someone tries to deploy your application to some no-server?
You will eventually get https://api.mydomain.app/api\v2\me, this is not a valid URL! Posix should be used if the PATH module is used to manipulate urls.