Skip to content

Commit 8d3bd42

Browse files
authored
feat: add 'PREACT_APP_' prefixed env vars automatically & pickup .env file (#1671)
1 parent fcd0375 commit 8d3bd42

File tree

12 files changed

+116
-14
lines changed

12 files changed

+116
-14
lines changed

.changeset/stupid-suns-crash.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'preact-cli': minor
3+
---
4+
5+
Any environment variables prefixed with 'PREACT_APP_' will automatically be available for reference and use in your application without having to configure `DefinePlugin` any more. Furthermore, if a `.env` file exists in the root of your application, any variables it defines will automatically be available for use.
6+
7+
Huge shout out to [robinvdvleuten](https://github.com/robinvdvleuten) who provided this functionality through the [`preact-cli-plugin-env-vars`](https://github.com/robinvdvleuten/preact-cli-plugin-env-vars) package in the past.

README.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -328,19 +328,33 @@ The default templates comes with a `.css` file for each component. You can start
328328

329329
### Using Environment Variables
330330

331-
You can reference and use environment variables in your `preact.config.js` by using `process.env`:
331+
You can reference and use any environment variable in your application that has been prefixed with `PREACT_APP_` automatically:
332+
333+
> `src/index.js`
332334
333335
```js
334-
export default {
335-
webpack(config, env, helpers, options) {
336-
if (process.env.MY_VARIABLE) {
337-
/** You can add a config here that will only used when your variable is truthy **/
338-
}
339-
},
340-
};
336+
console.log(process.env.PREACT_APP_MY_VARIABLE);
341337
```
342338

343-
If you'd like to use these variables in your application, you can use the [DefinePlugin] config from our recipes wiki.
339+
If your variable is not prefixed, you can still add it manually by using your `preact.config.js` (see [DefinePlugin] config in the recipes wiki).
340+
341+
You can set and store variables using a `.env` file in the root of your project:
342+
343+
> `.env`
344+
345+
```
346+
PREACT_APP_MY_VARIABLE="my-value"
347+
```
348+
349+
You can also reference environment variables in your `preact.config.js`:
350+
351+
```js
352+
export default (config, env, helpers, options) => {
353+
if (process.env.MY_VARIABLE) {
354+
/** You can add a config here that will only used when your variable is truthy **/
355+
}
356+
};
357+
```
344358

345359
### Route-Based Code Splitting
346360

packages/cli/lib/commands/build.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ async function command(src, argv) {
9292
argv.production = toBool(argv.production);
9393

9494
let cwd = resolve(argv.cwd);
95+
96+
// we explicitly set the path as `dotenv` otherwise uses
97+
// `process.cwd()` -- this would cause issues in environments
98+
// like mono-repos or our test suite subjects where project root
99+
// and the current directory differ.
100+
require('dotenv').config({ path: resolve(cwd, '.env') });
101+
95102
if (argv.clean === void 0) {
96103
let dest = resolve(cwd, argv.dest);
97104
await promisify(rimraf)(dest);

packages/cli/lib/commands/watch.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const runWebpack = require('../lib/webpack/run-webpack');
22
const { isPortFree, toBool, warn } = require('../util');
33
const { validateArgs } = require('./validate-args');
44
const getPort = require('get-port');
5+
const { resolve } = require('path');
56

67
const options = [
78
{
@@ -105,6 +106,14 @@ async function command(src, argv) {
105106
argv.sw = toBool(argv.sw);
106107
}
107108

109+
let cwd = resolve(argv.cwd);
110+
111+
// we explicitly set the path as `dotenv` otherwise uses
112+
// `process.cwd()` -- this would cause issues in environments
113+
// like mono-repos or our test suite subjects where project root
114+
// and the current directory differ.
115+
require('dotenv').config({ path: resolve(cwd, '.env') });
116+
108117
argv.port = await determinePort(argv.port);
109118

110119
if (argv.https || process.env.HTTPS) {

packages/cli/lib/lib/webpack/webpack-base-config.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,21 @@ module.exports = function createBaseConfig(env) {
306306

307307
plugins: [
308308
new webpack.NoEmitOnErrorsPlugin(),
309-
new webpack.DefinePlugin({
310-
'process.env.NODE_ENV': JSON.stringify(
311-
isProd ? 'production' : 'development'
312-
),
313-
}),
309+
new webpack.DefinePlugin(
310+
Object.keys(process.env)
311+
.filter(key => /^PREACT_APP_/.test(key))
312+
.reduce(
313+
(env, key) => {
314+
env[`process.env.${key}`] = JSON.stringify(process.env[key]);
315+
return env;
316+
},
317+
{
318+
'process.env.NODE_ENV': JSON.stringify(
319+
isProd ? 'production' : 'development'
320+
),
321+
}
322+
)
323+
),
314324
new webpack.ProvidePlugin({
315325
h: ['preact', 'h'],
316326
Fragment: ['preact', 'Fragment'],

packages/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
"critters-webpack-plugin": "^2.5.0",
9898
"cross-spawn-promise": "^0.10.1",
9999
"css-loader": "^5.2.4",
100+
"dotenv": "^16.0.0",
100101
"ejs-loader": "^0.5.0",
101102
"envinfo": "^7.8.1",
102103
"esm": "^3.2.25",

packages/cli/tests/build.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,19 @@ describe('preact build', () => {
309309
);
310310
});
311311
});
312+
313+
it('should use a custom `.env` with prefixed environment variables', async () => {
314+
let dir = await subject('custom-dotenv');
315+
await build(dir);
316+
317+
const bundleFile = (await readdir(`${dir}/build`)).find(file =>
318+
/bundle\.\w{5}\.js$/.test(file)
319+
);
320+
const transpiledChunk = await readFile(
321+
`${dir}/build/${bundleFile}`,
322+
'utf8'
323+
);
324+
// "Hello World!" should replace 'process.env.PREACT_APP_MY_VARIABLE'
325+
expect(transpiledChunk.includes('console.log("Hello World!")')).toBe(true);
326+
});
312327
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PREACT_APP_MY_VARIABLE="Hello World!"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log(process.env.PREACT_APP_MY_VARIABLE);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"private": true,
3+
"name": "preact-custom-dotenv"
4+
}

0 commit comments

Comments
 (0)