unplugin-transform-import-meta
v0.0.6
Published
Transform ImportMeta properties and methods at build-time.
Downloads
15
Maintainers
Readme
unplugin-transform-import-meta
[!WARNING]
Extending
import.metais not something to do lightly.Please read the guidance and reserved key registry in WinterTC's import-meta-registry before using this plugin: https://github.com/WinterTC55/import-meta-registry.
This plugin targets library/framework authors who have a strong, well‑justified need for build‑time only metadata. In most application-level cases you should not need this plugin.
Prefer official mechanisms from your bundler/platform (e.g. environment variables, define/replace features, virtual modules, configuration files) before introducing custom
import.meta.*keys.
Transform import.meta.* properties and methods at build-time across Vite, Rollup, Webpack, Rspack, esbuild, Rolldown, and Farm.
- Replace
import.meta.SOME_PROPwith literals (string/number/boolean/bigint/RegExp/null) - Evaluate
import.meta.someMethod(...)with your function and inline the literal result - Guard against reserved
import.metakeys for each bundler and common registries
ESM-only. Requires Node.js >= 20.19.0.
Install
npm i -D unplugin-transform-import-meta
# pnpm add -D unplugin-transform-import-meta
# yarn add -D unplugin-transform-import-meta
# bun add -d unplugin-transform-import-metaLanguage Support
[x] JavaScript/TypeScript:
.js,.ts,.jsx,.tsx(auto-detected)[x] Astro:
.astroIf you use Astro, add the optional peer dependency:
npm i -D @astrojs/compiler
[ ] Vue / Svelte: not yet supported. Contributions welcome!
- See #3 / #4 for details.
Quick Start
Define how import.meta should be resolved via bindings (the ImportMetaBindings shape).
import type { Options } from "unplugin-transform-import-meta"
// shared bindings (TypeScript for clarity)
const options: Options = {
bindings: {
values: {
APP_NAME: "my-app",
APP_ENV: "production",
FEATURE_FLAG: true,
},
functions: {
version: (v) => `v${v}`,
asset: (path) => `/static/${path}`,
},
},
};// vite.config.ts
import { defineConfig } from 'vite'
import TransformImportMeta from 'unplugin-transform-import-meta/vite'
export default defineConfig({
plugins: [
TransformImportMeta(options),
],
})// rollup.config.ts
import TransformImportMeta from 'unplugin-transform-import-meta/rollup'
export default {
plugins: [TransformImportMeta(options)],
}// rolldown.config.ts
import TransformImportMeta from 'unplugin-transform-import-meta/rolldown'
export default {
plugins: [TransformImportMeta(options)],
}// webpack.config.ts
import TransformImportMeta from 'unplugin-transform-import-meta/webpack'
export default {
plugins: [TransformImportMeta(options)],
}// rspack.config.ts
import TransformImportMeta from 'unplugin-transform-import-meta/rspack'
export default {
plugins: [TransformImportMeta(options)],
}import { build } from 'esbuild'
import TransformImportMeta from 'unplugin-transform-import-meta/esbuild'
await build({
plugins: [TransformImportMeta(options)],
})// farm.config.ts
import TransformImportMeta from 'unplugin-transform-import-meta/farm'
export default {
plugins: [TransformImportMeta(options)],
}What It Does (Before ➜ After)
Given this source code:
// input.ts
console.log(import.meta.APP_NAME)
console.log(import.meta.APP_ENV)
console.log(import.meta.version('1.2.3'))
console.log(import.meta.asset('logo.svg'))It becomes:
console.log("my-app")
console.log("production")
console.log("v1.2.3")
console.log("/static/logo.svg")In .astro files, the plugin transforms in all contexts:
- Frontmatter
--- ... --- <script>blocks- Template expressions like
{import.meta.APP_NAME}
Options
import type { Options } from 'unplugin-transform-import-meta'
const plugin = TransformImportMeta({
enforce: 'pre',
include: [/\.[cm]?[jt]sx?$/, /\.astro$/],
exclude: [/node_modules/],
bindings: {
values: {
APP_NAME: 'my-app',
APP_ENV: 'production',
// key can be nested via dot-path
"flags.FOO_RELEASED": true,
},
functions: {
// args must be literals; non-literals are passed as null
version: (v) => `v${v}`,
},
},
} satisfies Options)enforce:'pre' | 'post'(default:'pre')- Changing
enforcecasually can break the plugin's behavior due to transform ordering across plugins and the bundler. - Only change it if you
know exactly what you're doing and need to coordinate ordering with other
transforms. The default
'pre'is recommended for most setups.
- Changing
include/exclude: Anyunplugin-utilsFilterPattern. Defaults process JS/TS and.astro, excludingnode_modules.bindings.values: Mapimport.meta.<dot.path>to a literal value.bindings.functions: Mapimport.meta.<method>to a function returning a literal.
Notes:
- Only literal values are inlined. Method arguments that are not literals are passed as
nullto your function. - Source maps are not generated by this plugin (returns
map: null).
Reserved Keys Safety
This plugin validates and throws early if your rules override reserved import.meta.* keys.
- WinterTC registry: please refer to https://github.com/WinterTC55/import-meta-registry for the canonical list. If new keys are added and our list lags behind, open a PR to update it here.
- For bundler-specific reservations, we intentionally avoid duplicating lists in this README to prevent drift. See the implementation at
src/core/reserved.tsfor the authoritative, up‑to‑date checks.
When a conflict is detected, you will get an error like:
The property name "import.meta.<name>" is reserved and cannot be used.Rename your property/method to a non-reserved name.
Runtime & Build Matrix
- Supported bundlers: Vite, Rollup, Rolldown, Webpack, Rspack, esbuild, Farm
- Languages: JS/TS/JSX/TSX and Astro
- ESM-only package; use modern toolchains
License
MIT License © 2025-PRESENT sushichan044
