Recently, I needed to create a node module that would copy a file from within the module into the repository that was using it. For this, I had to find the file's exact location within the node module. I needed to make sure that this script would work independently from where it was installed. Luckily, this is where import.meta.url
came in.
import.meta.url
The very useful import.meta.url
will return a string that contains the full URL to the module that it is being called from. As MDN mentions, when you are using this outside of the browser and in a Node.js environment, this will actually be a file path. In my case, I was dealing with a Node.js environment (which is older than Node.js v20), which is why I'll focus on that here.
__dirname
Some might wonder: why don't you just use __dirname
? Well, if you want to use ES modules, this is simply not available. It means you're going to have to use import.meta.url
instead. PLUS, you have to do some extra work as well. We'll get to that.
Why not just use process.cwd()
?
If you use process.cwd()
, you will actually get the directory where you started the process. In the case of using a module within a repository, it would mean that you would get the repository's directory, not the module's directory. And that is something we do not want here. This is why you need to use import.meta.url
to get the module's actual directory.
Getting the actual directory
Speaking of, let's get that directory. So my file was inside of a foo
folder (of course it wasn't, but let's pretend it was). I wanted to copy a file from within the foo
folder to the repository that was using the module. I used import.meta.url
which got me a filepath to the current module I was in.
I had to make sure that this filepath was a normal url first, which is where fileURLToPath
from the url
module came into play. After this, I passed this path to the dirname
function (from the path
module) to get the directory of the module. And voila. I had the directory of the module.
// In Node.js version 14.14 and up:
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const moduleDirectory = dirname(fileURLToPath(import.meta.url));
Modern Node.js
With Node.js version 21.2, a new option called import.meta.dirname
was introduced. While this only works for file modules, it would do the trick:
const moduleDirectory = import.meta.dirname;
Using the directory
Now that I had the directory, I could actually copy my files to the root folder of my repository. To do this I used the fs
module to read the file and write it to the repository's directory. And this is also where process.cwd()
came in.
import { readFileSync, writeFileSync } from 'node:fs';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const moduleDirectory = dirname(fileURLToPath(import.meta.url));
const file = readFileSync(`${moduleDirectory}/foo/file.txt`);
writeFileSync(`${process.cwd()}/file.txt`, file);
And that is how you can copy a file from within a module to the repository it's being used in. Voila!
Top comments (0)