Passing environment-dependent variables in webpack
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"], };
};