Topics

Jump to a topic.

Search questions

Find a question by title, tag, or summary.

What is import.meta?

Questions in this chapter (7)
  • Draft
  • easy
  • Askedsometimes
  • Verified October 2026

Answer

import.meta is a meta property: syntax, not a variable lookup, and it is a SyntaxError outside a module (in CommonJS you get Cannot use 'import.meta' outside a module). Each module has its own object: the engine creates a null-prototype object the first time the module reads it, asks the host to fill in properties, caches it, and returns the same object on every later read. It is extensible, so you can add properties.

The language specifies no properties. By convention, hosts provide:

  • import.meta.url: the module's absolute URL. In browsers it is the script's URL (for an inline module, the document's URL); in Node.js it is a file: URL.
  • import.meta.resolve(specifier): resolves a specifier the way import would, relative to this module, and returns a URL string. It does not load anything and, in Node.js, returns a string synchronously.
  • import.meta.filename and import.meta.dirname (Node.js only): the absolute path of the file (symlinks resolved) and its directory, available for file: modules. They replace CommonJS __filename and __dirname.
  • import.meta.main (Node.js): true in the entry module, the counterpart to require.main === module. Node.js documents it as Stability 1.0, early development.

The common job is finding files next to the module. Relative paths in fs calls resolve against the working directory, not the module, so build the location from import.meta.url or dirname.

Example

import { readFileSync } from 'node:fs';
import { dirname } from 'node:path';

console.log(import.meta.url.startsWith('file:///'));
console.log(import.meta.dirname === dirname(import.meta.filename));
const data = JSON.parse(readFileSync(new URL('./data.json', import.meta.url), 'utf8'));
console.log(data);
console.log(import.meta.resolve('./data.json') === new URL('./data.json', import.meta.url).href);
// → true
// → true
// → { k: 1 }
// → true

data.json contains { "k": 1 }.

Pitfalls

  • Using __dirname or __filename in an ES module. They don't exist.
  • Treating import.meta.url as a path. It is a URL string, so pass it to new URL(...) or fileURLToPath, and don't concatenate path strings onto it.
  • Relying on dirname/filename in code that also runs in browsers. They are Node.js-only conventions, and Node.js defines them only for file: modules.
  • Assuming one import.meta for the app. Each module gets its own object, so import.meta.url always names the file it is written in.

Follow-ups

How is import.meta.resolve different from import()?
It only computes the URL that import() would use, synchronously, and loads nothing. A specifier that can't be resolved may throw (Node.js: ERR_MODULE_NOT_FOUND for a missing package), but a missing file at a valid path does not.
Where do the properties come from?
The host. The spec calls HostGetImportMetaProperties to get key/value pairs and HostFinalizeImportMeta for any final adjustments; the default implementation adds nothing.
What replaces require.resolve and __dirname in ESM?
import.meta.resolve() and import.meta.dirname (or new URL('.', import.meta.url)).

Exercises

Same object or not

// shared.mjs
export const meta = import.meta;
// main.mjs
import { meta } from './shared.mjs';
console.log(meta === import.meta, meta.url.endsWith('shared.mjs'), Object.getPrototypeOf(meta));