Skip to content

isBrowserEnv() stops tree shaking in bundlers and leaks node specific code to browser bundles #4452

@joshuaellis

Description

@joshuaellis

Describe the bug

Description

#3704 introduced ENV_TARGET as a compile-time define so build tools can tree-shake environment-specific code. It wrapped createScriptNode/loadScriptNode in sdk/src/node.ts and the loadEntryDom/loadEntryNode branch in runtime-core/src/utils/load.ts with ENV_TARGET guards. However, there are ~7 remaining isBrowserEnv() call sites in runtime-core that were not updated. These were originally added in #2482 for SSR support. Because isBrowserEnv is a function call, bundlers cannot statically evaluate it and the dead branches survive tree-shaking – see module-federation/vite#274.

Proposal

Change isBrowserEnv from a function to a top-level const that respects ENV_TARGET:

declare const ENV_TARGET: 'web' | 'node';

export const isBrowserEnv = typeof ENV_TARGET !== 'undefined'
  ? ENV_TARGET === 'web'
  : typeof window !== 'undefined' && typeof window.document !== 'undefined';

When a build tool defines ENV_TARGET = 'web' (via webpack DefinePlugin, rspack, or Vite config.define), the bundler collapses this to:

export const isBrowserEnv = true;

Bundlers can propagate top-level constants. Every if(isBrowserEnv) becomes if(true), and the else branches are dead-code-eliminated across the entire runtime. When ENV_TARGET is not defined, behavior is unchanged — it falls back to the runtime typeof window check.

Notes

I imagine this is considered a breaking change so I didn't want to make the PR without checking first – open to discussion.

Reproduction

module-federation/vite#274

Used Package Manager

pnpm

System Info

System:
    OS: macOS 14.6.1
    CPU: (11) arm64 Apple M3 Pro
    Memory: 57.67 MB / 36.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 24.12.0 - /Users/josh.ellis/.nvm/versions/node/v24.12.0/bin/node
    npm: 11.6.2 - /Users/josh.ellis/.nvm/versions/node/v24.12.0/bin/npm
    pnpm: 10.28.2 - /Users/josh.ellis/Library/pnpm/pnpm
    bun: 1.2.13 - /opt/homebrew/bin/bun
  Browsers:
    Chrome: 145.0.7632.68
    Firefox: 147.0.3
    Safari: 17.6

Validations

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