Using import.meta.url for Relative Paths in ES Modules
In modern JavaScript ECMAScript Modules (ESM),
import.meta.url provides the absolute URL of the currently
executing module file. By combining this property with the standard
URL constructor, developers can reliably resolve relative
asset paths—such as images, worker scripts, and JSON data—relative to
the location of the module itself rather than the current working
directory or the base HTML document.
What is
import.meta.url?
import.meta is a host-populated object available in all
JavaScript ES modules. Its url property returns a string
containing the full URL of the current module.
Depending on the runtime environment: - In a web
browser, it returns the network URL (for example,
https://example.com/scripts/utils.js). - In
Node.js or Deno, it returns a local
file URL scheme (for example,
file:///path/to/project/scripts/utils.js).
How Relative Path Resolution Works
The standard way to resolve a relative path using
import.meta.url is to pass the relative path and
import.meta.url to the standard URL
constructor:
const assetUrl = new URL('./assets/logo.png', import.meta.url);The URL constructor accepts two arguments: 1.
input: The target relative or absolute path. 2.
base: The base URL against which the input is resolved.
When import.meta.url is used as the base, the
constructor calculates the final location using standard URL resolution
rules:
./assets/logo.pngresolves to theassetsdirectory located in the same directory as the module.../data/config.jsonmoves up one directory level from the module before navigating down./styles/main.cssresolves relative to the root origin of the module URL.
The resulting URL object includes properties like
.href (the full resolved URL string) and
.pathname (the file path without the origin).
Common Use Cases
1. Loading Static Assets in the Browser
const image = new Image();
image.src = new URL('./images/icon.svg', import.meta.url).href;
document.body.appendChild(image);2. Spawning Web Workers
Bundlers and modern browsers recognize worker instantiation when
written with import.meta.url:
const worker = new Worker(
new URL('./worker.js', import.meta.url),
{ type: 'module' }
);3. File System Operations in Node.js
Because Node.js ES modules do not provide __dirname or
__filename, import.meta.url is used alongside
the node:url module to read local files:
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
const filePath = fileURLToPath(new URL('./data.json', import.meta.url));
const fileData = await fs.readFile(filePath, 'utf-8');Bundler Integration
Modern build tools like Vite, Webpack, and Rollup analyze
new URL('...', import.meta.url) syntax statically during
the build process. When detected, the bundler copies the referenced
asset to the distribution folder, processes it (including hashing for
cache busting), and updates the resolved URL to match the final
production output path automatically.