DEV Community

Karin
Karin

Posted on • Originally published at khendrikse.netlify.app on

Find your module's location

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));
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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)