Visitar URL original
Bun.serve HTML routes rewrite import.meta.env.X to hmr.importMeta.env.X, but the runtime never defines env — TypeError in the browser · Issue #48817 · oven-sh/bun · GitHub
Skip to content

Bun.serve HTML routes rewrite import.meta.env.X to hmr.importMeta.env.X, but the runtime never defines env — TypeError in the browser #48817

Open

Description

@martijnbokma

What version of Bun is running?

1.4.0 (macOS arm64). Also reproduced on 1.4.4.

What platform is your computer?

macOS arm64

What steps can reproduce the bug?

index.html:

<!doctype html><html><body><script type="module" src="./main.ts"></script></body></html>

main.ts:

console.log("MY_VAR", (import.meta as any).env.MY_VAR);

serve.ts:

import index from "./index.html";
const s = Bun.serve({ port: 0, routes: { "/": index }, development: true });
const html = await (await fetch(s.url)).text();
const src = html.match(/src="([^"]+\.js)"/)?.[1]!;
const js = await (await fetch(new URL(src, s.url))).text();
console.log(js.split("\n").filter((l) => l.includes("MY_VAR")).join("\n"));
s.stop(true);
bun serve.ts

What is the expected behavior?

import.meta.env.X in browser code served through Bun.serve HTML routes resolves to a defined object — e.g. populated from BUN_PUBLIC_* variables / [serve.static] env config — or is statically replaced like DEV/PROD/MODE already are. The page must not crash.

What do you see instead?

The dev bundle rewrites the read to hmr.importMeta.env:

console.log("MY_VAR", hmr.importMeta.env.MY_VAR);

but the client runtime's importMeta getter only defines url, main, require and hot — there is no env property:

get importMeta(){let Z={url:`${location.origin}/${this.id}`,main:!1,require:this.require.bind(this),get hot(){throw Error("import.meta.hot cannot be used indirectly.")}}; ...

So any import.meta.env.X read in browser code throws at runtime:

TypeError: Cannot read properties of undefined (reading 'MY_VAR')

which crashes the whole module on page load.

Notes:

  • Reproduced on 1.4.0 and 1.4.4, with and without --hot.
  • Adding env = "BUN_PUBLIC_*" under [serve.static] in bunfig.toml and exporting BUN_PUBLIC_* variables does not populate importMeta.env either.
  • DEV, PROD and MODE are statically replaced (true/false/"development" in dev); every other key is rewritten to hmr.importMeta.env.* and crashes.
  • With development: false the read is left verbatim as import.meta.env.MY_VAR, which is equally undefined in a real browser.
  • Related: Bun.build / bun build leave import.meta.env.DEV, PROD and MODE in a browser bundle, while Bun.serve HTML routes replace them #47170 reports the same rewrite asymmetry for DEV/PROD/MODE between Bun.serve HTML routes and Bun.build. This issue is specifically about the runtime env object never being defined, which turns the rewrite into a guaranteed TypeError for any non-special-cased key.

Workaround we shipped downstream

Guard the read (typeof import.meta.env === "undefined", which keeps member expressions intact for Vite define replacement) and fetch env values from a JSON route the dev server provides.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions