dotenv-webpack

A secure Webpack plugin that loads dotenv variables into your bundle while exposing only what your code actually references.

Library
npm
v9.0.0
1,295 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
48 /100 Fair
Development Activity 4
Maintenance 32
Community 56
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
67 /100 Good
Architecture 68
Code Quality 78
Innovation 50
Learning Curve 70

dotenv-webpack wraps dotenv-defaults and Webpack’s DefinePlugin to bring environment variables from a .env file into your client bundle. Instead of injecting every variable in the file, it scans for process.env.[NAME] references in your source and only bakes in the ones your code explicitly uses — so secrets like database passwords or API keys that live in .env but are never referenced never end up in shipped JavaScript.

On top of the core load-and-replace behavior, it layers in .env.example “safe mode” validation (fail the build if a required variable is missing), .env.defaults fallback values, system environment variable merging for CI, and variable expansion/interpolation for values that reference other variables. Since Webpack 5 dropped its automatic Node.js polyfills, the plugin also stubs any remaining unreplaced process.env references so browser bundles don’t throw at runtime.

What You Get

  • Compile-time replacement of process.env.NAME references using Webpack’s DefinePlugin, so only referenced variables reach the bundle
  • “Safe mode” via an .env.example blueprint file that throws a build error when a required variable is missing or empty
  • .env.defaults fallback support (via dotenv-defaults) for shared default values across environments
  • Optional systemvars merging so CI/CD environment variables are picked up alongside the .env file
  • Variable expansion/interpolation (${OTHER_VAR} syntax) for composing values from other variables
  • Automatic process.env stubbing under Webpack 5+ targets that lack a Node.js process polyfill, avoiding runtime crashes in browser bundles
  • Configurable path, prefix (e.g. swap process.env. for import.meta.env.), and silent-mode logging

Common Use Cases

  • Injecting API base URLs, feature flags, or public keys into a frontend bundle without exposing unrelated secrets from a shared .env file
  • Enforcing that all required environment variables are set before a CI build succeeds, using safe mode against .env.example
  • Sharing one .env file across multiple packages in a monorepo, each with its own Webpack config pointing at a relative path
  • Migrating a Node-only codebase that used plain dotenv into a bundled frontend build without redoing environment variable handling

Under The Hood

Architecture The entire plugin is a single Dotenv class in src/index.js implementing Webpack’s standard plugin interface via apply(compiler). Internally it follows a clear pipeline: gatherVariables() merges system environment variables, the parsed .env file, and optional .env.defaults values (validating against an .env.example blueprint when safe mode is enabled), then formatData() shapes the result into the key/value map Webpack’s DefinePlugin expects, applying variable interpolation and a Webpack-5-specific process.env stub before handing the assembled DefinePlugin instance to the compiler. There’s no build step or bundler needed to consume the plugin itself, and state is scoped entirely to the options passed into the constructor, so multiple instances in a monorepo don’t interfere with each other.

Tech Stack Plain CommonJS JavaScript with a single runtime dependency, dotenv-defaults (itself a wrapper around dotenv adding defaults-file support), and a peer dependency on webpack ^4 || ^5. Type consumers get a hand-written types/index.d.ts using export = CJS-style declarations rather than a TypeScript build pipeline. Development tooling includes Jest 30 for testing, standard for zero-config linting enforced through a Husky precommit hook, and jsdoc for generating API docs from inline comments.

Code Quality Tests in test/index.test.js run real Webpack compilations against a matrix of fixture .env files (empty, simple, one-empty, missing-one, systemvars, expanded, defaults) and assert on the literal replaced content of the emitted bundle rather than mocking Webpack internals, giving high confidence the plugin behaves correctly end-to-end. Coverage collection is enabled by default in the Jest config, and standard linting is enforced pre-commit. Error handling follows a deliberate two-tier pattern: silent-by-default warnings for missing .env files, but hard throws when safe mode is enabled and a required variable is absent — an explicit, documented choice rather than a swallowed failure.

API Design The entire public surface is a single constructor option object with well-chosen defaults (path: './.env', prefix: 'process.env.'), so the plugin works with zero configuration in the common case. Every option is documented with JSDoc directly above the constructor, and advanced behaviors — safe mode, defaults files, system variable merging, expansion, a custom prefix for import.meta.env.-style access — are additive flags rather than separate APIs, keeping the boilerplate needed to get started minimal.

Used by 5 apps in this directory

TypeScript
97%
AGPL 3.0

Bigcapital

Invoicing Finance

3,916

Self-hostable double-entry accounting platform with invoicing, inventory, multi-currency, and real-time financial reporting for small and medium businesses.

View details
90
Repo Health
77
Technical
61
Dependency
Built with
TypeScript 97%
Updated 6 days ago
PHP
78%
Other

Craft CMS

CMS

3,609

A developer-first PHP CMS with clean-slate content modeling, auto-generated GraphQL API, and a four-tier edition system that scales from solo projects to enterprise deployments.

View details
96
Repo Health
83
Technical
62
Dependency
Built with
PHP 78%
JavaScript 14%
Updated 5 days ago
TypeScript
61%
EPL-2.0

Huly Platform

Collaboration · Project Management · Team Chat

27,797

Open-source all-in-one workspace that replaces Linear, Jira, Slack, and Notion for product and engineering teams.

View details
90
Repo Health
86
Technical
62
Dependency
Built with
TypeScript 61%
Svelte 34%
Updated 6 days ago
JavaScript
26%
AGPL 3.0

Omnivore

Bookmarks Archiving · Knowledge Management · Note Taking

16,265

Self-hosted read-it-later platform with highlights, newsletters, PDFs, and seamless Obsidian and Logseq integration.

View details
90
Repo Health
74
Technical
65
Dependency
Built with
JavaScript 26%
TypeScript 25%
HTML 19%
Updated 5 days ago
TypeScript
51%
ZLIB

Portainer

Devops

38,590

A lightweight, open-source web UI that puts Docker, Kubernetes, and Podman management within reach of any team—no CLI expertise required.

View details
92
Repo Health
79
Technical
65
Dependency
Built with
TypeScript 51%
Go 38%
Updated 1 weeks ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers