From 133b0de33482c08e2ab55108b3c7bf7eb1ea494f Mon Sep 17 00:00:00 2001 From: lupuszr Date: Fri, 13 Jul 2018 17:51:02 +0200 Subject: [PATCH 1/2] feat(docz-core): expose filtered env variables Add dotenv to support reading .env files Expose env varables to browser which start with REACT_APP_ ANGULAR_APP_ VUE_APP_ NODE_Add dotenv --- packages/docz-core/package.json | 1 + .../docz-core/src/bundlers/webpack/config.ts | 2 + .../docz-core/src/bundlers/webpack/dotenv.ts | 88 +++++++++++++++++++ yarn.lock | 4 + 4 files changed, 95 insertions(+) create mode 100644 packages/docz-core/src/bundlers/webpack/dotenv.ts diff --git a/packages/docz-core/package.json b/packages/docz-core/package.json index e3142aa48..492efbbcc 100644 --- a/packages/docz-core/package.json +++ b/packages/docz-core/package.json @@ -40,6 +40,7 @@ "cpy": "^7.0.1", "deepmerge": "^2.1.1", "detect-port": "^1.2.3", + "dotenv": "^6.0.0", "express": "^4.16.3", "fast-glob": "^2.2.2", "file-loader": "^1.1.11", diff --git a/packages/docz-core/src/bundlers/webpack/config.ts b/packages/docz-core/src/bundlers/webpack/config.ts index 6756606ca..302bdd52d 100644 --- a/packages/docz-core/src/bundlers/webpack/config.ts +++ b/packages/docz-core/src/bundlers/webpack/config.ts @@ -11,6 +11,7 @@ import { BabelRC } from '../../utils/babelrc' import * as paths from '../../config/paths' import * as loaders from './loaders' import { Env } from './' +import { getClientEnvironment } from './dotenv' const uglify = new UglifyJs({ parallel: true, @@ -229,6 +230,7 @@ export const createConfig = (babelrc: BabelRC) => ( { BASE_URL: JSON.stringify(base), NODE_ENV: JSON.stringify(env), + ...getClientEnvironment(base).stringified, }, ]) diff --git a/packages/docz-core/src/bundlers/webpack/dotenv.ts b/packages/docz-core/src/bundlers/webpack/dotenv.ts new file mode 100644 index 000000000..ed9cf8c3a --- /dev/null +++ b/packages/docz-core/src/bundlers/webpack/dotenv.ts @@ -0,0 +1,88 @@ +import fs from 'fs' +import path from 'path' + +const appDir = fs.realpathSync(process.cwd()) +const resolveApp = (relativePath: any) => path.resolve(appDir, relativePath) + +const dotenv = resolveApp('.env') + +const NODE_ENV = process.env.NODE_ENV +// if (!NODE_ENV) { +// throw new Error( +// 'The NODE_ENV environment variable is required but was not specified.' +// ) +// } + +// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use +const dotenvFiles = [ + `$dotenv}.${NODE_ENV}.local`, + `$dotenv}.${NODE_ENV}`, + // Don't include `.env.local` for `test` environment + // since normally you expect tests to produce the same + // results for everyone + NODE_ENV !== 'test' && `$dotenv}.local`, + dotenv, +].filter(Boolean) + +// Load environment variables from .env* files. Suppress warnings using silent +// if this file is missing. dotenv will never modify any environment variables +// that have already been set. Variable expansion is supported in .env files. +// https://github.com/motdotla/dotenv +dotenvFiles.forEach(dotenvFile => { + require('dotenv').config({ + path: dotenvFile, + }) +}) + +// We support resolving modules according to `NODE_PATH`. +// This lets you use absolute paths in imports inside large monorepos: +// https://github.com/facebook/create-react-app/issues/253. +// It works similar to `NODE_PATH` in Node itself: +// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders +// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. +// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. +// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421 +// We also resolve them to make sure all tools using them work consistently. +const appDirectory = fs.realpathSync(process.cwd()) +process.env.NODE_PATH = (process.env.NODE_PATH || '') + .split(path.delimiter) + .filter(folder => folder && !path.isAbsolute(folder)) + .map(folder => path.resolve(appDirectory, folder)) + .join(path.delimiter) + +// Grab NODE_ENV and REACT_APP_ or ANGULAR_APP_ or VUE_APP_* environment variables +// and prepare them to be +// injected into the application via DefinePlugin in Webpack configuration. +const APP_TEST = /^(REACT_APP_)|(ANGULAR_APP_)|(VUE_APP_)/i + +interface RT { + [name: string]: any +} +export const getClientEnvironment = (publicUrl: string) => { + const raw: RT = Object.keys(process.env) + .filter(key => APP_TEST.test(key)) + .reduce( + (env: RT, key) => { + env[key] = process.env[key] + return env + }, + { + // Useful for determining whether we’re running in production mode. Most + // importantly, it switches React into the correct mode. + NODE_ENV: process.env.NODE_ENV || 'development', + // Useful for resolving the correct path to static assets in `public`. For + // example, . This should + // only be used as an escape hatch. Normally you would put images into the `src` + // and `import` them in code to get their + PUBLIC_URL: publicUrl, + } + ) + const stringified = { + 'process.env': Object.keys(raw).reduce((env: RT, key) => { + env[key] = JSON.stringify(raw[key]) + return env + }, {}), + } + + return { raw, stringified } +} diff --git a/yarn.lock b/yarn.lock index 371cb90ac..636ea01af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4434,6 +4434,10 @@ dot-prop@^4.1.0: dependencies: is-obj "^1.0.0" +dotenv@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.0.0.tgz#24e37c041741c5f4b25324958ebbc34bca965935" + duplexer2@^0.1.4, duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" From ad052a93018184343e1f2b3e70ed8f53e65da06e Mon Sep 17 00:00:00 2001 From: lupuszr Date: Fri, 13 Jul 2018 21:01:20 +0200 Subject: [PATCH 2/2] feat(docz-core): expose filtered env variables --- packages/docz-core/src/bundlers/webpack/config.ts | 2 +- .../src/{bundlers/webpack => config}/dotenv.ts | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) rename packages/docz-core/src/{bundlers/webpack => config}/dotenv.ts (90%) diff --git a/packages/docz-core/src/bundlers/webpack/config.ts b/packages/docz-core/src/bundlers/webpack/config.ts index 302bdd52d..eeacb653a 100644 --- a/packages/docz-core/src/bundlers/webpack/config.ts +++ b/packages/docz-core/src/bundlers/webpack/config.ts @@ -9,9 +9,9 @@ import UglifyJs from 'uglifyjs-webpack-plugin' import { Config as Args } from '../../commands/args' import { BabelRC } from '../../utils/babelrc' import * as paths from '../../config/paths' +import { getClientEnvironment } from '../../config/dotenv' import * as loaders from './loaders' import { Env } from './' -import { getClientEnvironment } from './dotenv' const uglify = new UglifyJs({ parallel: true, diff --git a/packages/docz-core/src/bundlers/webpack/dotenv.ts b/packages/docz-core/src/config/dotenv.ts similarity index 90% rename from packages/docz-core/src/bundlers/webpack/dotenv.ts rename to packages/docz-core/src/config/dotenv.ts index ed9cf8c3a..4e88d7384 100644 --- a/packages/docz-core/src/bundlers/webpack/dotenv.ts +++ b/packages/docz-core/src/config/dotenv.ts @@ -7,16 +7,11 @@ const resolveApp = (relativePath: any) => path.resolve(appDir, relativePath) const dotenv = resolveApp('.env') const NODE_ENV = process.env.NODE_ENV -// if (!NODE_ENV) { -// throw new Error( -// 'The NODE_ENV environment variable is required but was not specified.' -// ) -// } // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use const dotenvFiles = [ - `$dotenv}.${NODE_ENV}.local`, - `$dotenv}.${NODE_ENV}`, + `${dotenv}.${NODE_ENV}.local`, + `${dotenv}.${NODE_ENV}`, // Don't include `.env.local` for `test` environment // since normally you expect tests to produce the same // results for everyone @@ -35,8 +30,6 @@ dotenvFiles.forEach(dotenvFile => { }) // We support resolving modules according to `NODE_PATH`. -// This lets you use absolute paths in imports inside large monorepos: -// https://github.com/facebook/create-react-app/issues/253. // It works similar to `NODE_PATH` in Node itself: // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.