A small Rollup/Vite plugin that allows bundled modules to access the filename and dirname of the original source module.
ECMAScript modules have access to an import.meta object, which allows them to
read learn where they are located relative to other resources. The
import.meta.url property allows a module to refer to its own location in order
to, e.g., create relative import paths to sibling modules.
If a module is fed through a bundler, however, import.meta.url will reflect
the bundle's location at runtime. There's no dynamic mechanism for a bundled
module to refer to its original location relative to other modules in the source
project.
rollup-filemeta seeks to provide this mechanism to Rollup bundles by
interpolating a local module's id value into its source code at build time.
The Rollup plugin is exported as a module fromrollup-filemeta/plugin. Add
rollup-filemeta/plugin to your Rollup or Vite configuration in the
standard way:
Deno:
$ deno add rollup-filemetanpm/Yarn/pnpm/etc. should use the jsr compatibility layer:
$ npx jsr -D rollup-filemeta// rollup.config.mjs
import filemeta from "rollup-filemeta/plugin";
export default {
// ... other bundle configuration
plugins: [
filemeta({
base: __dirname, // optional: set a base path for briefer interpolated module paths
}),
],
};The plugin accepts these configuration options:
base: Optionally set a base path which will be trimmed from interpolated paths to local modules. This could be helpful to avoid embedding machine-specific path information into a bundle.
The plugin provides a virtual module called rollup-filemeta, to be imported
into your project's local module(s):
// <path-to-project>/src/my-module.mjs
import meta from "rollup-filemeta";
console.log(meta.filename); // logs the whole filepath to the module: <path-to-project>/src/my-module.js
console.log(meta.dirname); // logs the directory path to the module: <path-to-project>/srcThis virtual module acts as a build-time macro: during the transform step
of a Rollup build, the import declaration is erased, and usages of
meta.filename or meta.dirname are rewritten to contain metadata about the
original, pre-bundled module.
The filename and dirname seek to resemble Node's import.meta.filename and
import.meta.dirname properties, but with Rollup module IDs. This means that
filename is the full path to the module file, not just the base name of the
file. dirname is the full path without the base name of the file. (I didn't
pick this convention!)
Constraints on usage: It's currently expected and enforced that the import
declaration for rollup-filemeta will strictly be a default import with a
single specifier only (though this specifier can be anything). Importing any of
the virtual module's exports directly will cause a Rollup build error. The
intention behind this constraint is code clarity: there's not yet any
first-class macro syntax for ECMAScript, and I think it's less confusing for a
member access from an imported identifier to transform/disappear than a bare
identifier expression. There's no technical constraint here, though, and it
could be relaxed in the future.
resolveImportMeta would also work to interpolate metadata about the original
module's file, except it's an output generation hook, not a build hook. This
means that modules served from a Vite dev server would not have any custom
import.meta properties resolved by resolveImportMeta, since it's never
called. Using a transform hook means both Vite dev servers and standard Rollup
builds use the same mechanism for interpolating file metadata.
Thank you to @Comandeer for their rollup-plugin-macros package and corresponding blog post, which aided the design of this plugin.