Reputation: 1835
I am new to webpack and worked out almost all build sections, but now the problem is that I want to pass the environment variables from a .env file to webpack config, so that I can pass that variables to my build files via webpack.DefinePlugin
plugin.
Currently I am able to to pass environment variable directly from webpack to to my build. Please see the code below which I used in webpack.
new webpack.DefinePlugin({
"API_URL": JSON.stringify("http://my-api.com"),
"FRONT_END_API_KEY" : "MYFRONTENDKEYGOESHERE"
}),
My package.json
build script is
"scripts": {
"start": "NODE_ENV=development webpack-dev-server --progress --port 8000 --content-base app/build/src"
}
Upvotes: 75
Views: 128693
Reputation: 801
In my case, I have many environments to support Ex: .env.local
, .env.dev
, ... etc. I have solved loading environment specific env file to webpack config as follows
Step 1: Create a file for a specific environment - Ex: .env.local
API_HOST=127.0.0.1
API_KEY=mysecretkey
...
Step 2: Create a webpack config common for all environments - webpack.common.js
...
...
const webpack = require('webpack')
const dotenv = require('dotenv')
...
...
module.exports = env => {
return {
resolve: {...},
devServer: {...},
module: {...},
plugins: [
new webpack.DefinePlugin(
{'process.env': JSON.stringify(dotenv.config(path: env.ENV_FILE}).parsed)})
}
}
Here the important thing to be noted is module.exports
should return a function instead of an object so that it can access the env variable (ENV_FILE
in this example) passed on by the environment specific webpack config file, such as webpack.local.js
(step 3).
Step 3: Create a environment specific webpack config file - webpack.local.js
const { merge } = require('webpack-merge')
const common = require('./webpack.common')
module.exports = env => merge(common(env), {
mode: 'development',
output: {
publicPath: 'http://localhost:3000',
},
devtool: 'inline-source-map',
devServer: {
watchFiles: ['src/**/*'],
hot: true,
port: 3000
},
})
In this environment specific file, webpack.common.js file is imported as a function (const common
) that gets called with env
parameter as part of the webpack merge
. Here env
parameter is populated by the --env
option in the webpack
command in the package.json
(step 4)
Step 4: Setup webpack commands in package.json
"scripts": {
"start": "webpack serve --open --env ENV_FILE=.env.local --config webpack.local.js",
"build:prod": "webpack --env ENV_FILE=.env.prod --config webpack.prod.js"
...
}
Here npm command start
serves up a local web server with webpack.local.js
as its webpack config. When the call gets into webpack.local.js
it populates ENV_FILE
key into the env
parameter in the function returned by module.exports
.
Similarly you can setup webpack.prod.js
which can be specific to your prod environment on the lines of webpack.local.js illustrated above.
Upvotes: 1
Reputation: 6094
The dotenv-flow-webpack can do this for you.
It is a webpack plugin that allows you to securely use environment variables within your javascript web application, loading them using dotenv-flow's .env*
files loading strategy.
dotenv-flow extends dotenv, adding support of
NODE_ENV
-specific.env*
files like.env.development
,.env.test
,.env.stage
, and.env.production
, and the appropriate.env*.local
overrides allowing your app to have multiple environments with selectively-adjusted environment variable setups and load them dynamically depending on the current NODE_ENV.
🌱 Inspired by CreateReactApp's storing configs in .env*
files approach,
the Twelve-Factor App methodology in general, and its store config in the environment section in particular.
Upvotes: 1
Reputation: 5728
You can use dotenv package for this purpose.
npm install dotenv --save
After installing the package, add this in the top of your config:
const webpack = require('webpack'); // only add this if you don't have yet
// replace accordingly './.env' with the path of your .env file
require('dotenv').config({ path: './.env' });
then in plugins
section, add this:
new webpack.DefinePlugin({
"process.env": JSON.stringify(process.env),
}),
Upvotes: 145
Reputation: 12080
First off...
It appears that you are trying to pass secrets into an angular application.
There is no such thing as a "secret" in client side (browser) javascript!!!
Anything passed into DefinePlugin
can be extracted with minimal effort.
Now that we've cleared that up....
Webpack now has the Environment Plugin which makes it a bit easier to pass env variables into the GlobalDefine plugin. From the docs:
new webpack.EnvironmentPlugin(['NODE_ENV', 'DEBUG']);
This is equivalent to the following DefinePlugin application:
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.DEBUG': JSON.stringify(process.env.DEBUG)
});
If you are using dotenv
to manage environment vars, you can use the dotenv webpack plugin.
It will only include variables that are referenced in your code, so as long as you don't reference your secrets, they won't be included.
Upvotes: 5
Reputation: 20406
I did get inspiration from the accepted answer, but it doesn't work for me. Maybe the API of dotenv has changed.
The following works for me
import dotenv from 'dotenv'
import { DefinePlugin } from 'webpack'
...
plugins: [
new DefinePlugin({
'process.env': JSON.stringify(dotenv.config().parsed)
})
]
...
Upvotes: 27
Reputation: 645
The simplest solution I found is to use this npm package: dotenv-webpack
Create a .env file
// .env
DB_HOST=127.0.0.1
DB_PASS=foobar
S3_API=mysecretkey
Add it to your Webpack config file
// webpack.config.js
const Dotenv = require('dotenv-webpack');
module.exports = {
...
plugins: [
new Dotenv()
]
...
};
Use in your code
// file1.js
console.log(process.env.DB_HOST);
// '127.0.0.1'
Resulting bundle
// bundle.js
console.log('127.0.0.1');
Upvotes: 10
Reputation: 2319
It doesn't match your case exactly (although partially), but I've found this formula to be working best for me.
I use a combination of 2 libs: dotenv to read the .env
file for the webpack.config.js
(configuration) needs, and webpack-dotenv-plugin for the validation (based on .env.example
file) and to pass all the vars from .env file to the application code:
Part of my webpack.config.js
:
// this is to load env vars for this config
require('dotenv').config({ // it puts the content to the "process.env" var. System vars are taking precedence
path: '.env.webpack',
});
// and this to pass env vars to the JS application
const DotenvPlugin = require('webpack-dotenv-plugin');
plugins section:
plugins: [
// ...
new DotenvPlugin({ // makes vars available to the application js code
path: '.env.webpack',
sample: '.env.webpack.example',
allowEmptyValues: true,
}),
// ...
]
Upvotes: 13
Reputation: 3644
From webpack docs:
The webpack command line environment option --env allows you to pass in as many environment variables as you like. Environment variables will be made accessible in your webpack.config.js. For example, --env.production or --env.NODE_ENV=local (NODE_ENV is conventionally used to define the environment type, see here.)
in your package.json
webpack --env.NODE_ENV=local --env.production --progress
in your webpack.config.js
module.exports = env => {
// Use env.<YOUR VARIABLE> here:
console.log('NODE_ENV: ', env.NODE_ENV) // 'local'
console.log('Production: ', env.production) // true
return {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
Upvotes: 2
Reputation: 121
I can't comment to clarify any info so my apologies for the answer.
You could do:
var env = require('.env');
then
new webpack.DefinePlugin({
"API_URL": JSON.stringify("http://my-api.com"),
"SECRET_KEY" : "MYSECRETKEYGOESHERE",
"env_property": env.property
}),
But I'm making assumptions about your .env file and the way its set up with this answer
Upvotes: 5