Skip to content

Commit

Permalink
feat: adding config for stubbing (#360)
Browse files Browse the repository at this point in the history
* fix: only stub `process.env` if not targeting node

* fix: use better replacement

* only dont stub on main thread electron

* add tests that use the compiler

* start converting old tests

* move more tests

* replace old tests

* fix errors

* fix race condition

* handle no dir error

* remove behavior changes

* drop node 8

* undo more fixes

* fix stubbing replacement, only stub on targets where we should

* remove deprecated code

* drop support for webpack <4

* merge stubIgnore PR

* update readme

* fix logic

* Update README.md

* skip stubbing on webpack 4, do not stub if target includes `node`

* handle target array

* move version check

* fix logic

* replace usage of `rmdirSync(..., { recursive: true })`

BREAKING CHANGE: dropping support for Node v8

BREAKING CHANGE: dropping support for webpack < 4

BREAKING CHANGE: automatically stubbing during compilation
  • Loading branch information
beeequeue committed Mar 5, 2021
1 parent b2da479 commit 67c0aeb
Show file tree
Hide file tree
Showing 8 changed files with 555 additions and 264 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
runs-on: ubuntu-18.04
strategy:
matrix:
node: [ '8', '10', '12', '14' ]
node: [ '10', '12', '14' ]
steps:
- name: 🛑 Cancel Previous Runs
uses: styfle/[email protected]
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Tests
test/output

# Logs
logs
*.log
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ Add `.env` to your `.gitignore` file

Due to the fact that we use `webpack.DefinePlugin` under the hood, we cannot support destructing as that breaks how this plugin is meant to be used. Because of this, please reference your variables without destructing. For more information about this, please review the issue [here](https://github.com/mrsteele/dotenv-webpack/issues/70).

## `process.env` stubbing / replacing

`process.env` is not polyfilled in Webpack 5+, leading to errors in environments where `process` is `null` (browsers).

We automatically replace any remaining `process.env`s in these environments with `"MISSING_ENV_VAR"` to avoid these errors.

If you are running into issues where you or another package you use interfaces with `process.env`, it might be best to set `ignoreStubs: true` and make sure you always reference variables that exist within your code (See [this issue](https://github.com/mrsteele/dotenv-webpack/issues/271) for more information).

## Properties

Use the following properties to configure your instance.
Expand All @@ -106,6 +114,7 @@ Use the following properties to configure your instance.
* **silent** (`false`) - If true, all warnings will be suppressed.
* **expand** (`false`) - Allows your variables to be "expanded" for reusability within your `.env` file.
* **defaults** (`false`) - Adds support for `dotenv-defaults`. If set to `true`, uses `./.env.defaults`. If a string, uses that location for a defaults file. Read more at [npm](https://www.npmjs.com/package/dotenv-defaults).
* **ignoreStub** (`false`) - Override the automatic check whether to stub `process.env`. [Read more here](#user-content-processenv-stubbing--replacing).

The following example shows how to set any/all arguments.

Expand Down
34 changes: 34 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
},
"jest": {
"coverageDirectory": "./coverage/",
"collectCoverage": true
"collectCoverage": true,
"watchPathIgnorePatterns": [
"output/.*?"
]
},
"keywords": [
"dotenv",
Expand All @@ -41,8 +44,11 @@
"url": "https://github.com/mrsteele/dotenv-webpack/issues"
},
"homepage": "https://github.com/mrsteele/dotenv-webpack#readme",
"engines": {
"node": ">=10"
},
"peerDependencies": {
"webpack": "^1 || ^2 || ^3 || ^4 || ^5"
"webpack": "^4 || ^5"
},
"dependencies": {
"dotenv-defaults": "^2.0.1"
Expand All @@ -52,6 +58,7 @@
"@babel/core": "^7.13.8",
"@babel/preset-env": "^7.13.9",
"@babel/register": "^7.13.8",
"fs-extra": "^9.1.0",
"husky": "^5.1.3",
"jest": "^25.5.4",
"jsdoc": "^3.6.6",
Expand Down
66 changes: 47 additions & 19 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const interpolate = (env, vars) => {
return env
}

const isMainThreadElectron = (target) =>
target.startsWith('electron') && target.endsWith('main')

class Dotenv {
/**
* The dotenv-webpack plugin.
Expand All @@ -30,21 +33,19 @@ class Dotenv {
this.config = Object.assign({}, {
path: './.env'
}, config)

this.checkDeprecation()

return new DefinePlugin(this.formatData(this.gatherVariables()))
}

checkDeprecation () {
const { sample, safe, silent } = this.config
// Catch older packages, but hold their hand (just for a bit)
if (sample) {
if (safe) {
this.config.safe = sample
}
this.warn('dotenv-webpack: "options.sample" is a deprecated property. Please update your configuration to use "options.safe" instead.', silent)
}
apply (compiler) {
const variables = this.gatherVariables()
const target = compiler.options.target ?? 'web'
const version = compiler.webpack.version
const data = this.formatData({
variables,
target,
version
})

new DefinePlugin(data).apply(compiler)
}

gatherVariables () {
Expand Down Expand Up @@ -121,10 +122,10 @@ class Dotenv {
return ''
}

formatData (vars = {}) {
formatData ({ variables = {}, target, version }) {
const { expand } = this.config
const formatted = Object.keys(vars).reduce((obj, key) => {
const v = vars[key]
const formatted = Object.keys(variables).reduce((obj, key) => {
const v = variables[key]
const vKey = `process.env.${key}`
let vValue
if (expand) {
Expand All @@ -133,7 +134,7 @@ class Dotenv {
} else if (v.indexOf('\\$') > 0) {
vValue = v.replace(/\\\$/g, '$')
} else {
vValue = interpolate(v, vars)
vValue = interpolate(v, variables)
}
} else {
vValue = v
Expand All @@ -144,12 +145,39 @@ class Dotenv {
return obj
}, {})

// fix in case of missing
formatted['process.env'] = '{}'
// We have to stub any remaining `process.env`s due to Webpack 5 not polyfilling it anymore
// https://github.com/mrsteele/dotenv-webpack/issues/240#issuecomment-710231534
// However, if someone targets Node or Electron `process.env` still exists, and should therefore be kept
// https://webpack.js.org/configuration/target
if (this.shouldStub({ target, version })) {
// Results in `"MISSING_ENV_VAR".NAME` which is valid JS
formatted['process.env'] = '"MISSING_ENV_VAR"'
}

return formatted
}

shouldStub ({ target: targetInput, version }) {
if (!version.startsWith('5')) {
return false
}

const targets = Array.isArray(targetInput) ? targetInput : [targetInput]

return targets.every(
target =>
// If we're not configured to never stub
this.config.ignoreStub !== true &&
// And
(
// We are configured to always stub
this.config.ignoreStub === false ||
// Or if we should according to the target
(!target.includes('node') && !isMainThreadElectron(target))
)
)
}

/**
* Load a file.
* @param {String} config.file - The file to load.
Expand Down
28 changes: 28 additions & 0 deletions test/fixtures/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* eslint-disable no-unused-vars */

// Basic
const TEST = process.env.TEST
const TEST2 = process.env.TEST2

// System
const PATH = process.env.PATH

// Expanded
const NODE_ENV = process.env.NODE_ENV
const BASIC = process.env.BASIC
const BASIC_EXPAND = process.env.BASIC_EXPAND
const MACHINE = process.env.MACHINE
const MACHINE_EXPAND = process.env.MACHINE_EXPAND
const UNDEFINED_EXPAND = process.env.UNDEFINED_EXPAND
const ESCAPED_EXPAND = process.env.ESCAPED_EXPAND
const MONGOLAB_DATABASE = process.env.MONGOLAB_DATABASE
const MONGOLAB_USER = process.env.MONGOLAB_USER
const MONGOLAB_PASSWORD = process.env.MONGOLAB_PASSWORD
const MONGOLAB_DOMAIN = process.env.MONGOLAB_DOMAIN
const MONGOLAB_PORT = process.env.MONGOLAB_PORT
const MONGOLAB_URI = process.env.MONGOLAB_URI
const MONGOLAB_USER_RECURSIVELY = process.env.MONGOLAB_USER_RECURSIVELY
const MONGOLAB_URI_RECURSIVELY = process.env.MONGOLAB_URI_RECURSIVELY
const WITHOUT_CURLY_BRACES_URI = process.env.WITHOUT_CURLY_BRACES_URI
const WITHOUT_CURLY_BRACES_USER_RECURSIVELY = process.env.WITHOUT_CURLY_BRACES_USER_RECURSIVELY
const WITHOUT_CURLY_BRACES_URI_RECURSIVELY = process.env.WITHOUT_CURLY_BRACES_URI_RECURSIVELY
Loading

0 comments on commit 67c0aeb

Please sign in to comment.