Passing environment-dependent variables in webpack
Asked Answered
C

18

393

I'm trying to convert an angular app from gulp to webpack. in gulp I use gulp-preprocess to replace some variables in the html page (e.g. database name) depending on the NODE_ENV. What is the best way of achieving a similar result with webpack?

Criticism answered 4/5, 2015 at 12:20 Comment(8)
Did alias work for you?Graphic
@bebraw: before I was able to get my head around aliases, I implemented the other solution you suggested based on DefinePlugin(). I do now see that alias would be a better solution and will probably refactor sometime - thanks. If you would like to include your two solutions in an answer I'll happily accept it.Criticism
Was directed here via console message. How to fix this in Browserify?Whipcord
Is this question trying to configure the SPA at build time or load time? I note two types of configuration for SPAs: 1) development or production mode, and 2) deployment environment, e.g. development, staging, production. I think NODE_ENV can be used to configure for (1) at build time but how do we configure for (2) at deployment, e.g. configuring a production mode for different deployment environments. I hope this is relevant to this question.Heeley
just webpack -p is sufficientYocum
@AshleyAitken Great question of which I couldn't find an answer on this thread (maybe i missed it), but posted this new thread: #44465004Waxwing
@DavidTesar Is this helpful? #40954900Heeley
Hi, I am trying to understand how this really works. DefinePlugin makes the variables accessible to the client application. It puts these variables in a global space. Does it mean these vars are available in the window object? Is it a good practice to do this?Heptad
T
496

There are two basic ways to achieve this.

DefinePlugin

new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),

Note that this will just replace the matches "as is". That's why the string is in the format it is. You could have a more complex structure, such as an object there but you get the idea.

EnvironmentPlugin

new webpack.EnvironmentPlugin(['NODE_ENV'])

EnvironmentPlugin uses DefinePlugin internally and maps the environment values to code through it. Terser syntax.

Alias

Alternatively you could consume configuration through an aliased module. From consumer side it would look like this:

var config = require('config');

Configuration itself could look like this:

resolve: {
    alias: {
        config: path.join(__dirname, 'config', process.env.NODE_ENV)
    }
}

Let's say process.env.NODE_ENV is development. It would map into ./config/development.js then. The module it maps to can export configuration like this:

module.exports = {
    testing: 'something',
    ...
};
Twelve answered 5/5, 2015 at 19:7 Comment(22)
Thanks for pointing out the fact that it replaces the matches "as is". I was struggling for a while to figure out why my code was throwing an error and it was because I wasn't wrapping the value in a JSON.stringify()Trinidad
Is there a reason you're doing JSON.stringify('development') instead of just '"development"'?Lolalolande
That gives the same result, correct. I'll tweak the answer to that form given it's a notch simpler.Graphic
If you're using ES2015, you can also use string interpolation - 'process.env.NODE_ENV': `"${process.env.NODE_ENV || 'development'}"`Appleby
@Lolalolande JSON.stringify('development') as is might not be really useful. Instead JSON.stringify(someVariable) can quite be!Stoicism
As suggested by user2688473 "${process.env.NODE_ENV || 'development'}" is much better choice, because allows you to override NODE_ENV in npm scripts and also override npm scripts by command line params.Adrianaadriane
@Adrianaadriane Thanks. I tweaked along those lines (ES5 style).Graphic
The variable is replaced when the webpack bundles the files. How do I achieve a deploy-time variable replacement depending on the environment I am deploying to?Fellers
You should set NODE_ENV to do that. How to set that depends on your platform.Graphic
How would I set the environment values at the package.json from windows? whenever I make a call, it results in 'YOUR_VARIABLE' is not recognized as an internal or external command, operable program or batch file.Rainout
I had success using a slightly different version of the first option, as found here: https://mcmap.net/q/87884/-minified-code-outside-of-node_env-39-production-39-this-means-slower-development-build-of-reduxMorn
@Morn Yeah, that's essentially the same. The advantage of nesting like that is that you can set multiple keys pretty easily. :)Graphic
Anyone had success with passing a function through a plugin variable? #43503386Klan
@JuhoVepsäläinen does this also work for external modules? could I pass some values as global constants to modules outside of my project?Rainout
@AnyulRivas Yeah. React uses process.env.NODE_ENV pattern and it works.Graphic
Yet another variation: EnvironmentConfig supports a nifty defaulting behavior, which I find intuitive: new webpack.EnvironmentPlugin({NODE_ENV: 'development'}) This provides a default only if NODE_ENV is not already defined, which it will be if you set it on the command line, as in NODE_ENV=production webpack ...Aftmost
I've just migrated to webpack v3 and the code doesn't work anymore. Any change on this matter @JuhoVepsäläinen?Rainout
@AnyulRivas It could be a bug in webpack 3. There have been quite a few issues with the release. Please check the issue tracker and open a new issue if you can't find a matching one.Graphic
What if i want to load variables to DefinePlugin from a .env file?Armington
@RameezRami How is the .env file defined? Are you using dotenv or something? It might be better to open a separate question for that.Graphic
Gotta say, the resolve "trick" is brilliant. I use resolve for hardcoded local packages but never thought of using it for external inputs. Now I can dynamically pass in an external config directory. Thanks!Mollymollycoddle
Resolve is great because it doesn't require a 3rd party pluginsBorsch
B
116

Just another option, if you want to use only a cli interface, just use the define option of webpack. I add the following script in my package.json :

"build-production": "webpack -p --define process.env.NODE_ENV='\"production\"' --progress --colors"

So I just have to run npm run build-production.

Bespectacled answered 24/3, 2016 at 14:6 Comment(5)
Is there documentation for this? I can't Google --define :(Teredo
For webpack@2, "-p" is already shortcut for --optimize-minimize --define process.env.NODE_ENV="production"Interspace
@Interspace Docs mention -p Equals to --optimize-minimize --optimize-occurence-order, so no mention of --define process.env.NODE_ENV="production". Is it something that's removed?Aldo
@NaderHadjiGhanbari It is in webpack version 2 webpack.js.org/api/cli/#shortcutsInterspace
Trying this in Oct 2023. Error: Unknown option '-p' and Error: Unknown option '--define'.Ida
T
91

I investigated a couple of options on how to set environment-specific variables and ended up with this:

I have 2 webpack configs currently:

// webpack.production.config.js

new webpack.DefinePlugin({
  'process.env':{
    'NODE_ENV': JSON.stringify('production'),
    'API_URL': JSON.stringify('http://localhost:8080/bands')
  }
}),
// webpack.config.js

new webpack.DefinePlugin({
  'process.env':{
    'NODE_ENV': JSON.stringify('development'),
    'API_URL': JSON.stringify('http://10.10.10.10:8080/bands')
  }
}),

In my code I get the value of API_URL in this way:

const apiUrl = process.env.API_URL;

Webpack docs have an example:

new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(true),
    VERSION: JSON.stringify("5fa3b9"),
    BROWSER_SUPPORTS_HTML5: true,
    TWO: "1+1",
    "typeof window": JSON.stringify("object")
})

With ESLint you need to specifically allow undefined variables in code, if you have no-undef rule on. Like this:

/*global TWO*/
console.log('Running App version ' + TWO);

If you're not into configuring too much, check out Create React App: Adding Custom Environment Variables. Under the hood CRA uses Webpack anyway.

Taxeme answered 15/7, 2016 at 9:48 Comment(10)
Did you find that this prevented any environment variables being passed in at run time? If you replace the whole of process.env then doesn't process.env.PORT for example resolve to undefined during the webpack build which means you can no longer override the port from the environment?Saidel
what is process? where is it coming from? if it's a node object, how does it get into the browser?Rank
This is a terrible solution, you have two webpack.configs almost entirely identical except for setting NODE_ENV and API_URLBooby
@BrianOgden Yep it is indeed, you should use something like webpack-merge for this: npmjs.com/package/webpack-merge - It's a bit out of scope for this question IMO.Taxeme
@thevangelist I finally figured out a simple solution,my premise was why would there be more than one webpack.config.js file, webpack should load different json configurations based on the environment cmd webpack call, here is my solution github.com/Sweetog/yet-another-angular2-boilerplateBooby
@BrianOgden I refactored some of my old code, ended up using webpack-merge with process.env.npm_lifecycle_event - this allows me to match the environment based on the name of the NPM script, say "if(TARGET === 'start') {" would target a script called "npm run start": See further explanation here: medium.com/@brianhan/…Taxeme
@thevangelist Thanks so much because of /*global TWO*/ with ESLintOuster
I recently had the pleasure of finding out that DefinePlugin doesn't allow overrides. So if you have a webpack.common.js and a webpack.prod.js deriving from it, your overrides in webpack.prod.js are going to be totally ignored.Marston
@I'llEatMyHat can you suggest an edit to the answer?Taxeme
Things have changed since then; you'll get a WARNING in DefinePlugin Conflicting values for 'FOOBAR' The solution is to just define the variables multiple times in the leaf nodes. Every webpack config except common.Marston
J
38

You can pass environment variables without additional plugins using --env

Webpack 2-4

webpack --config webpack.config.js --env.foo=bar

Webpack 5+ (without.)

webpack --config webpack.config.js --env foo=bar

Then, use the variable in webpack.config.js:

module.exports = function(env) {
    if (env.foo === 'bar') {
        // do something
    }
}

Further Reading: Webpack 2.0 doesn't support custom command line arguments? #2254

Jennette answered 21/10, 2016 at 7:21 Comment(3)
Note, the --env syntax appears to have changed at some point in webpack 5: npx webpack --env goal=localStatfarad
And what if my module.exports object is split across two webpack.config files using a merge? First file: module.exports = {/*stuff*/} Second file: const { merge } = require("webpack-merge"); const common = require("./webpack.common.js"); module.exports = merge(common, {/*stuff*/} How do I turn both objects into one function so that I can get access to env?Aphoristic
Obviously, this only works in the build script and does not bundle the env variables into the app.Veridical
K
31

You can directly use the EnvironmentPlugin available in webpack to have access to any environment variable during the transpilation.

You just have to declare the plugin in your webpack.config.js file:

var webpack = require('webpack');

module.exports = {
    /* ... */
    plugins: [
        new webpack.EnvironmentPlugin(['NODE_ENV'])
    ]
};

Note that you must declare explicitly the name of the environment variables you want to use.

Kosse answered 20/6, 2016 at 16:7 Comment(3)
There's an example in the webpack docs with this very use case. github.com/webpack/docs/wiki/list-of-plugins#environmentpluginEngrossing
If you want to put your environment variables in a .env file, you can use the dotenv package and initialize it in webpack.config.js. npmjs.com/package/dotenvMethanol
Little typo: not plugins = [ but plugins: [Dailey
I
17

To add to the bunch of answers personally I prefer the following:

const webpack = require('webpack');
const prod = process.argv.indexOf('-p') !== -1;

module.exports = {
  ...
  plugins: [
    new webpack.DefinePlugin({
      process: {
        env: {
          NODE_ENV: prod? `"production"`: '"development"'
        }
      }
    }),
    ...
  ]
};

Using this there is no funky env variable or cross-platform problems (with env vars). All you do is run the normal webpack or webpack -p for dev or production respectively.

Reference: Github issue

Irita answered 2/10, 2016 at 3:15 Comment(1)
When defining values for process prefer 'process.env.NODE_ENV': JSON.stringify('production') over process: { env: { NODE_ENV: JSON.stringify('production') } }. Using the latter will overwrite the process object which can break compatibility with some modules that expect other values on the process object to be defined.Faitour
M
15

Since my Edit on the above post by thevangelist wasn't approved, posting additional information.

If you want to pick value from package.json like a defined version number and access it through DefinePlugin inside Javascript.

{"version": "0.0.1"}

Then, Import package.json inside respective webpack.config, access the attribute using the import variable, then use the attribute in the DefinePlugin.

const PACKAGE = require('../package.json');
const _version = PACKAGE.version;//Picks the version number from package.json

For example certain configuration on webpack.config is using METADATA for DefinePlugin:

const METADATA = webpackMerge(commonConfig({env: ENV}).metadata, {
  host: HOST,
  port: PORT,
  ENV: ENV,
  HMR: HMR,
  RELEASE_VERSION:_version//Version attribute retrieved from package.json
});

new DefinePlugin({
        'ENV': JSON.stringify(METADATA.ENV),
        'HMR': METADATA.HMR,
        'process.env': {
          'ENV': JSON.stringify(METADATA.ENV),
          'NODE_ENV': JSON.stringify(METADATA.ENV),
          'HMR': METADATA.HMR,
          'VERSION': JSON.stringify(METADATA.RELEASE_VERSION)//Setting it for the Scripts usage.
        }
      }),

Access this inside any typescript file:

this.versionNumber = process.env.VERSION;

The smartest way would be like this:

// webpack.config.js
plugins: [
    new webpack.DefinePlugin({
      VERSION: JSON.stringify(require("./package.json").version)
    })
  ]

Thanks to Ross Allen

Mantissa answered 7/11, 2016 at 12:17 Comment(0)
Y
12

Just another answer that is similar to @zer0chain's answer. However, with one distinction.

Setting webpack -p is sufficient.

It is the same as:

--define process.env.NODE_ENV="production"

And this is the same as

// webpack.config.js
const webpack = require('webpack');

module.exports = {
  //...

  plugins:[
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    })
  ]
};

So you may only need something like this in package.json Node file:

{
  "name": "projectname",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "debug": "webpack -d",
    "production": "webpack -p"
  },
  "author": "prosti",
  "license": "ISC",
  "dependencies": {    
    "webpack": "^2.2.1",
    ...
  }
}

Just a few tips from the DefinePlugin:

The DefinePlugin allows you to create global constants which can be configured at compile time. This can be useful for allowing different behavior between development builds and release builds. For example, you might use a global constant to determine whether logging takes place; perhaps you perform logging in your development build but not in the release build. That's the sort of scenario the DefinePlugin facilitates.


That this is so you can check if you type webpack --help

Config options:
  --config  Path to the config file
                         [string] [default: webpack.config.js or webpackfile.js]
  --env     Enviroment passed to the config, when it is a function

Basic options:
  --context    The root directory for resolving entry point and stats
                                       [string] [default: The current directory]
  --entry      The entry point                                          [string]
  --watch, -w  Watch the filesystem for changes                        [boolean]
  --debug      Switch loaders to debug mode                            [boolean]
  --devtool    Enable devtool for better debugging experience (Example:
               --devtool eval-cheap-module-source-map)                  [string]
  -d           shortcut for --debug --devtool eval-cheap-module-source-map
               --output-pathinfo                                       [boolean]
  -p           shortcut for --optimize-minimize --define
               process.env.NODE_ENV="production" 

                      [boolean]
  --progress   Print compilation progress in percentage                [boolean]
Yocum answered 9/2, 2017 at 0:15 Comment(0)
C
7

I found the following solution to be easiest to setup environment variable for Webpack 2:

For example we have a webpack settings:

var webpack = require('webpack')

let webpackConfig = (env) => { // Passing envirmonment through
                                // function is important here
    return {
        entry: {
        // entries
        },

        output: {
        // outputs
        },

        plugins: [
        // plugins
        ],

        module: {
        // modules
        },

        resolve: {
        // resolves
        }

    }
};

module.exports = webpackConfig;

Add Environment Variable in Webpack:

plugins: [
    new webpack.EnvironmentPlugin({
       NODE_ENV: 'development',
       }),
]

Define Plugin Variable and add it to plugins:

    new webpack.DefinePlugin({
        'NODE_ENV': JSON.stringify(env.NODE_ENV || 'development')
    }),

Now when running webpack command, pass env.NODE_ENV as argument:

webpack --env.NODE_ENV=development

// OR

webpack --env.NODE_ENV development

Now you can access NODE_ENV variable anywhere in your code.

Counterpoise answered 16/10, 2017 at 11:42 Comment(0)
E
4

I prefer using .env file for different environment.

  1. Use webpack.dev.config to copy env.dev to .env into root folder
  2. Use webpack.prod.config to copy env.prod to .env

and in code

use

require('dotenv').config(); const API = process.env.API ## which will store the value from .env file

Enthusiast answered 6/11, 2016 at 11:28 Comment(0)
H
4

My workaround for the webpack version "webpack": "^4.29.6" is very simple.

//package.json
{
...
 "scripts": {
    "build": "webpack --mode production",
    "start": "webpack-dev-server --open --mode development"
  },
}

you can pass --mode parameter with your webpack commnad then in webpack.config.js

 // webpack.config.json
 module.exports = (env,argv) => {
        return {
           ...
           externals: {
            // global app config object
            config: JSON.stringify({
                apiUrl: (argv.mode==="production") ? '/api' : 'localhost:3002/api'
            })
        }
}

And I use baseurl in my code like this

// my api service
import config from 'config';
console.log(config.apiUrl) // like fetch(`${config.apiUrl}/users/user-login`)
Heteropterous answered 30/12, 2020 at 8:6 Comment(1)
This is the best answer imoSubsidiary
C
3

To add to the bunch of answers:

Use ExtendedDefinePlugin instead of DefinePlugin

npm install extended-define-webpack-plugin --save-dev.

ExtendedDefinePlugin is much simpler to use and is documented :-) link

Because DefinePlugin lacks good documentation, I want to help out, by saying that it actually works like #DEFINE in c#.

#if (DEBUG)
        Console.WriteLine("Debugging is enabled.");
#endif

Thus, if you want to understand how DefinePlugin works, read the c# #define doucmentation. link

Craniate answered 27/10, 2016 at 22:24 Comment(0)
S
3

dotenv-webpack

A secure webpack plugin that supports dotenv and other environment variables and only exposes what you choose and use.

with some workaround with configuration based on defaults option to achieve that, once the package has .env.defaults file to as initial values for env variables you can use it for development and let .env for your production.

Usage

  • install the package
npm install dotenv-webpack --save-dev
  • Create a .env.defaults file
API_URL='dev_url/api/'
  • create a .env file leave it empty, let defaults works, update it on your deploy process
  • config webpack - webpack.config.js
new Dotenv({
  defaults: true 
})
  • dev environement test file.js
console.log(process.env.API_URL)
// Outputs: dev_url/api/
  • on build, update empty .env file
API_URL='prod_url/api/'

dotenv-webpack will use this to and override env.defaults

  • prod environement test file.js
console.log(process.env.API_URL)
// Outputs: prod_url/api/

dotenv-webpack
dotenv-defaults

Surat answered 1/4, 2021 at 13:20 Comment(0)
D
2

Here is a way that has worked for me and has allowed me keep my environment variables DRY by reusing a json file.

const webpack = require('webpack');
let config = require('./settings.json');
if (__PROD__) {
    config = require('./settings-prod.json');
}

const envVars = {};
Object.keys(config).forEach((key) => {
    envVars[key] = JSON.stringify(config[key]);
});

new webpack.DefinePlugin({
    'process.env': envVars
}),
Deiform answered 19/1, 2018 at 15:3 Comment(0)
M
2

Since Webpack v4, simply setting mode in your Webpack config will set the NODE_ENV for you (via DefinePlugin). Docs here.

Manizales answered 11/2, 2019 at 5:40 Comment(1)
seems this supports only 'production' or 'development' strings though... as per the docs : webpack.js.org/configuration/modeFrederickfredericka
G
1

I'm not a huge fan of...

new webpack.DefinePlugin({
  'process.env': envVars
}),

...as it does not provides any type of security. instead, you end up boosting your secret stuff, unless you add a webpack to gitignore 🤷‍♀️ there is a better solution.

Basically with this config once you compile your code all the process env variables will be removed from the entire code, there is not going to be a single process.env.VAR up thanks to the babel plugin transform-inline-environment-variables PS if you do not want to end up with a whole bunch of undefines, make sure you call the env.js before webpack calls babel-loader, that's why it is the first thing webpack calls. the array of vars in babel.config.js file must match the object on env.js. now there is only one mow thing to do. add a .env file put all your env variables there, the file must be at the root of the project or feel free to add it where ever u want, just make sure to set the same location on the env.js file and also add it to gitignore

const dotFiles = ['.env'].filter(Boolean);

if (existsSync(dotFiles)) {
    require("dotenv-expand")(require("dotenv").config((dotFiles)));
}

If you want to see the whole babel + webpack + ts get it from heaw https://github.com/EnetoJara/Node-typescript-babel-webpack.git

and same logic applies to react and all the other 💩

config
---webpack.js
---env.js
src
---source code world
.env
bunch of dotFiles

env.js

"use strict";
/***
I took the main idea from CRA, but mine is more cooler xD
*/
const {realpathSync, existsSync} = require('fs');
const {resolve, isAbsolute, delimiter} = require('path');

const NODE_ENV = process.env.NODE_ENV || "development";

const appDirectory = realpathSync(process.cwd());

if (typeof NODE_ENV !== "string") {
    throw new Error("falle and stuff");
}

const dotFiles = ['.env'].filter(Boolean);

if (existsSync(dotFiles)) {
    require("dotenv-expand")(require("dotenv").config((dotFiles)));
}

process.env.NODE_PATH = (process.env.NODE_PATH || "")
    .split(delimiter)
    .filter(folder => folder && isAbsolute(folder))
    .map(folder => resolve(appDirectory, folder))
    .join(delimiter);

const ENETO_APP = /^ENETO_APP_/i;

module.exports = (function () {
    const raw = Object.keys ( process.env )
        .filter ( key => ENETO_APP.test ( key ) )
        .reduce ( ( env, key ) => {
                env[ key ] = process.env[ key ];
                return env;
            },
            {
                BABEL_ENV: process.env.ENETO_APP_BABEL_ENV,
                ENETO_APP_DB_NAME: process.env.ENETO_APP_DB_NAME,
                ENETO_APP_DB_PASSWORD: process.env.ENETO_APP_DB_PASSWORD,
                ENETO_APP_DB_USER: process.env.ENETO_APP_DB_USER,
                GENERATE_SOURCEMAP: process.env.ENETO_APP_GENERATE_SOURCEMAP,
                NODE_ENV: process.env.ENETO_APP_NODE_ENV,
                PORT: process.env.ENETO_APP_PORT,
                PUBLIC_URL: "/"
            } );

    const stringyField = {
        "process.env": Object.keys(raw).reduce((env, key)=> {
            env[key]=JSON.stringify(raw[key]);
            return env;
        },{}),

    };

    return {
        raw, stringyField
    }
})();

webpack file with no plugins troll

"use strict";

require("core-js");
require("./env.js");

const path = require("path");
const nodeExternals = require("webpack-node-externals");

module.exports = env => {
    return {
        devtool: "source-map",
        entry: path.join(__dirname, '../src/dev.ts'),
        externals: [nodeExternals()],
        module: {
            rules: [
                {
                    exclude: /node_modules/,
                    test: /\.ts$/,
                    use: [
                        {
                            loader: "babel-loader",
                        },
                        {
                            loader: "ts-loader"
                        }
                    ],
                },
                {
                    test: /\.(png|jpg|gif)$/,
                    use: [
                        {
                            loader: "file-loader",
                        },
                    ],
                },
            ],
        },
        node: {
            __dirname: false,
            __filename: false,
        },
        optimization: {
            splitChunks: {
                automaticNameDelimiter: "_",
                cacheGroups: {
                    vendor: {
                        chunks: "initial",
                        minChunks: 2,
                        name: "vendor",
                        test: /[\\/]node_modules[\\/]/,
                    },
                },
            },
        },
        output: {
            chunkFilename: "main.chunk.js",
            filename: "name-bundle.js",
            libraryTarget: "commonjs2",
        },
        plugins: [],
        resolve: {
            extensions: ['.ts', '.js']
        }   ,
        target: "node"
    };
};

babel.config.js

module.exports = api => {

    api.cache(() => process.env.NODE_ENV);

    return {

        plugins: [
            ["@babel/plugin-proposal-decorators", { legacy: true }],
            ["@babel/plugin-transform-classes", {loose: true}],
            ["@babel/plugin-external-helpers"],
            ["@babel/plugin-transform-runtime"],
            ["@babel/plugin-transform-modules-commonjs"],
            ["transform-member-expression-literals"],
            ["transform-property-literals"],
            ["@babel/plugin-transform-reserved-words"],
            ["@babel/plugin-transform-property-mutators"],
            ["@babel/plugin-transform-arrow-functions"],
            ["@babel/plugin-transform-block-scoped-functions"],
            [
                "@babel/plugin-transform-async-to-generator",
                {
                    method: "coroutine",
                    module: "bluebird",
                },
            ],
            ["@babel/plugin-proposal-async-generator-functions"],
            ["@babel/plugin-transform-block-scoping"],
            ["@babel/plugin-transform-computed-properties"],
            ["@babel/plugin-transform-destructuring"],
            ["@babel/plugin-transform-duplicate-keys"],
            ["@babel/plugin-transform-for-of"],
            ["@babel/plugin-transform-function-name"],
            ["@babel/plugin-transform-literals"],
            ["@babel/plugin-transform-object-super"],
            ["@babel/plugin-transform-shorthand-properties"],
            ["@babel/plugin-transform-spread"],
            ["@babel/plugin-transform-template-literals"],
            ["@babel/plugin-transform-exponentiation-operator"],
            ["@babel/plugin-proposal-object-rest-spread"],
            ["@babel/plugin-proposal-do-expressions"],
            ["@babel/plugin-proposal-export-default-from"],
            ["@babel/plugin-proposal-export-namespace-from"],
            ["@babel/plugin-proposal-logical-assignment-operators"],
            ["@babel/plugin-proposal-throw-expressions"],
            [
                "transform-inline-environment-variables",
                {
                    include: [
                        "ENETO_APP_PORT",
                        "ENETO_APP_NODE_ENV",
                        "ENETO_APP_BABEL_ENV",
                        "ENETO_APP_DB_NAME",
                        "ENETO_APP_DB_USER",
                        "ENETO_APP_DB_PASSWORD",
                    ],
                },
            ],
        ],
        presets: [["@babel/preset-env",{
            targets: {
                node: "current",
                esmodules: true
            },
            useBuiltIns: 'entry',
            corejs: 2,
            modules: "cjs"
        }],"@babel/preset-typescript"],
    };
};
Gosney answered 20/8, 2019 at 12:6 Comment(5)
"You end up boosting your secret stuff, unless you add a webpack to gitignore." @Gosney can you expand upon that at all?Villiers
Basically your bundle ends up with out the process.env.BLAHBLAH and puts the actual value. For example instead of having process.env.NODE_ENV u end up with “production”, I mean that’s not the best example but imagine a secret key. Your bundle will have the actual value and who knows what that wired string stands for 🤷‍♀️Gosney
Hmmm - yes, those values will be interpolated in the built version, but presumably you're not pushing that to GitHub...Villiers
Though, @Katie, the code shared above is "a bit" over the top (since it (a) simply includes all proposals available at the time (doubt the production app actually needing this config exists at all) and (b) voluntarily creates and unmaintainable solo-mission for what?), that and the long yet much less "correct" answer aside, the dude's got a point when it comes to the doubtful practice of embedding secrets in code that is often shipped to untrusted, unknown clients over http thousands of times a day.Ripen
It might be minified, it might even be heavily transpiled, but the hypothetical API key is still a plain text series of unicode characters conveniently delivered to the client in perfectly human-readable form. The ONLY RIGHT WAY is for no secret ever needing to leave the realm of your server / network / virtual private cloud. Your client knows one API and one API only and that is YOUR public network gateway. If your client needs to request a 3rd party service, you provide a shallow service on the edge of your VPC that proxies her request to the 3rd party. Validate and throttle while at it.Ripen
P
1

now 2020, i am face to same question, but for this old question, there are so many new answer, just list some of it:

  • this is webpack.config.js
plugins: [
        new HtmlWebpackPlugin({
            // 1. title is the parameter, you can use in ejs template
            templateParameters:{
                title: JSON.stringify(someting: 'something'),
            },
        }), 


        //2. BUILT_AT is a parameter too. can use it.
        new webpack.DefinePlugin({
            BUILT_AT: webpack.DefinePlugin.runtimeValue(Date.now,"some"),

        }),

        //3. for webpack5, you can use global variable: __webpack_hash__
        //new webpack.ExtendedAPIPlugin()
    ],
    //4. this is not variable, this is module, so use 'import tt' to use it.
    externals: { 
        'ex_title': JSON.stringify({
            tt: 'eitentitle',
        })
    },

the 4 ways only basic, there are even more ways that i believe. but i think maybe this 4ways is the most simple.

Penchant answered 15/11, 2020 at 9:24 Comment(0)
C
0

The one from Juho Vepsäläinen works for me (webpack library)

EnvironmentPlugin

new webpack.EnvironmentPlugin(['NODE_ENV'])

EnvironmentPlugin uses DefinePlugin internally and maps the environment values to code through it. Terser syntax.

Cyprus answered 29/2 at 15:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.