diff --git a/bin/sprinklers3 b/bin/sprinklers3
new file mode 100755
index 0000000..cccd1ad
--- /dev/null
+++ b/bin/sprinklers3
@@ -0,0 +1,9 @@
+#!/usr/bin/env node
+
+const { run } = require("@oclif/command");
+const flush = require("@oclif/command/flush");
+const handleError = require("@oclif/errors/handle");
+
+run()
+ .then(flush)
+ .catch(handleError);
diff --git a/client/env.js b/client/env.js
index 4559427..cf7b349 100644
--- a/client/env.js
+++ b/client/env.js
@@ -1,58 +1,45 @@
const fs = require("fs");
-const path = require("path");
+const dotenv = require("dotenv");
const paths = require("../paths")
-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 = [
- `${paths.dotenv}.${NODE_ENV}.local`,
- `${paths.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" && `${paths.dotenv}.local`,
- paths.dotenv,
-].filter(Boolean);
+const validEnvs = ["production", "development"];
-// 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.
-// https://github.com/motdotla/dotenv
-dotenvFiles.forEach(dotenvFile => {
- if (fs.existsSync(dotenvFile)) {
- require("dotenv").config({
- path: dotenvFile,
- });
+exports.loadEnv = function loadEnv(env) {
+ if (validEnvs.indexOf(env) === -1) {
+ throw new Error("Must specify webpack --env as one of: " + validEnvs.join(','));
}
-});
-// We support resolving modules according to `NODE_PATH`.
-// This lets you use absolute paths in imports inside large monorepos:
-// https://github.com/facebookincubator/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/facebookincubator/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);
+ const dotenvFiles = [
+ `${paths.dotenv}.${env}.local`,
+ `${paths.dotenv}.${env}`,
+ // Don"t include `.env.local` for `test` environment
+ // since normally you expect tests to produce the same
+ // results for everyone
+ env !== "test" && `${paths.dotenv}.local`,
+ paths.dotenv,
+ ].filter(Boolean);
+
+ dotenvFiles.forEach(dotenvFile => {
+ if (fs.existsSync(dotenvFile)) {
+ dotenv.config({
+ path: dotenvFile,
+ });
+ }
+ });
+
+ delete require.cache[require.resolve("../paths")]; // so new env applies
+
+ return {
+ isProd: env === "production",
+ isDev: env === "development"
+ };
+}
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in Webpack configuration.
const REACT_APP = /^REACT_APP_/i;
-exports.getClientEnvironment = function getClientEnvironment(publicUrl) {
+exports.getClientEnvironment = function getClientEnvironment(env, publicUrl) {
const raw = Object.keys(process.env)
.filter(key => REACT_APP.test(key))
.reduce(
@@ -62,7 +49,7 @@ exports.getClientEnvironment = function getClientEnvironment(publicUrl) {
}, {
// 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",
+ NODE_ENV: process.env.NODE_ENV || env,
// 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
diff --git a/client/webpack.config.js b/client/webpack.config.js
index 42c1629..e47a42f 100644
--- a/client/webpack.config.js
+++ b/client/webpack.config.js
@@ -11,53 +11,58 @@ const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
-const { getClientEnvironment } = require("./env");
-const paths = require("../paths");
+const { loadEnv, getClientEnvironment } = require("./env");
-// Webpack uses `publicPath` to determine where the app is being served from.
-// It requires a trailing slash, or the file assets will get an incorrect path.
-const publicPath = paths.publicPath;
-// `publicUrl` is just like `publicPath`, but we will provide it to our app
-// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
-// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
-const publicUrl = paths.publicUrl.slice(0, -1);
-// Source maps are resource heavy and can cause out of memory issue for large source files.
-const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
-// Get environment variables to inject into our app.
-const environ = getClientEnvironment(publicUrl);
+function getConfig(env) {
+ const { isProd, isDev } = loadEnv(env);
-const postCssConfig = {
- loader: require.resolve("postcss-loader"),
- options: {
- // Necessary for external CSS imports to work
- // https://github.com/facebookincubator/create-react-app/issues/2677
- ident: "postcss",
- plugins: () => [
- require("postcss-flexbugs-fixes"),
- require("postcss-preset-env")({
- stage: 0
- })
- ]
- }
-};
+ const paths = require("../paths");
-const sassConfig = {
- loader: require.resolve("sass-loader"),
- options: {}
-};
+ // Webpack uses `publicPath` to determine where the app is being served from.
+ // It requires a trailing slash, or the file assets will get an incorrect path.
+ const publicPath = paths.publicPath;
+ // `publicUrl` is just like `publicPath`, but we will provide it to our app
+ // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
+ // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
+ const publicUrl = paths.publicUrl.slice(0, -1);
+ // Source maps are resource heavy and can cause out of memory issue for large source files.
+ const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
+ const shouldExtractCss = process.env.EXTRACT_CSS
+ ? process.env.EXTRACT_CSS === "true"
+ : isProd;
+ // Get environment variables to inject into our app.
+ const environ = getClientEnvironment(env, publicUrl);
+
+ const postCssConfig = {
+ loader: require.resolve("postcss-loader"),
+ options: {
+ // Necessary for external CSS imports to work
+ // https://github.com/facebookincubator/create-react-app/issues/2677
+ ident: "postcss",
+ plugins: () => [
+ require("postcss-flexbugs-fixes"),
+ require("postcss-preset-env")({
+ stage: 0
+ })
+ ]
+ }
+ };
+
+ const sassConfig = {
+ loader: require.resolve("sass-loader"),
+ options: {}
+ };
-const rules = env => {
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject