2

I'm having a nightmare with using environment variables in my SPFx project. I have:

  • a .env in the root of my project
  • variables within this file all starting with REACT_APP_
  • references to these variables using process.env.REACT_APP_
  • restarted gulp, cleaned and built many times
  • installed dotenv-webpack
  • installed dotenv
  • added 'node' to the types in tsconfig.json
  • confirmed I can read process.env.NODE_ENV

Any variables inside my .env file just appear as 'undefined' when I try reading them and view with console.log. Is there something I am missing? I thought this was an easy thing to set up.

.env:

REACT_APP_TEMPLATE_LIST='text'

WebPart.ts:

console.log(process.env.REACT_APP_TEMPLATE_LIST)

This reads as undefined.

Please help!

3
  • 1
    Try following this for dotenv: digitalworkplace365.wordpress.com/2020/03/05/… and this for DefinePlugin: sharepointpals.com/post/…. Let me know if this works for you. Commented Mar 10, 2023 at 9:50
  • You know what, I had looked at that link before, and dismissed it because I was getting errors in one of the files it tells you to create. So I just looked back on it, searched on the errors, and fixed them with a missing semi colon!! nice one for reassuring me it was the right way to go :) All working now.
    – Bentura
    Commented Mar 10, 2023 at 12:25
  • Great, glad it worked for you. Commented Mar 10, 2023 at 12:41

1 Answer 1

2

Create a file process-env.js like:

"use strict";
 
const fs = require("fs");
const path = require("path");
 
const NODE_ENV = process.env.NODE_ENV || "dev";
const dotEnvPath = path.resolve(process.cwd(), ".env");
 
const dotenvFiles = [
  `${dotEnvPath}.${NODE_ENV}.local`,
  `${dotEnvPath}.${NODE_ENV}`,
  NODE_ENV !== "test" && `${dotEnvPath}.local`,
  dotEnvPath
].filter(Boolean);
 
dotenvFiles.forEach(dotenvFile => {
  if (fs.existsSync(dotenvFile)) {
    require("dotenv-expand")(
      require("dotenv").config({
        path: dotenvFile
      })
    );
  }
});
 
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 SPFX_ = /^SPFX_/i;
 
function getClientEnvironment() {
  const raw = Object.keys(process.env)
    .filter(key => SPFX_.test(key))
    .reduce((env, key) => {
      env[key] = process.env[key];
      return env;
    }, {});
 
  const stringified = {
    "process.env": Object.keys(raw).reduce((env, key) => {
      env[key] = JSON.stringify(raw[key]);
      return env;
    }, {})
  };
 
  return { raw, stringified };
}
 
module.exports = getClientEnvironment;

Next, append gulpfile.js and add this right before the build.initialize() call:

const webpack = require("webpack");
const getClientEnvironment = require("./process-env");
 
build.configureWebpack.mergeConfig({
  additionalConfiguration: cfg => {
    let pluginDefine = null;
    for (var i = 0; i < cfg.plugins.length; i++) {
      var plugin = cfg.plugins[i];
      if (plugin instanceof webpack.DefinePlugin) {
        pluginDefine = plugin;
      }
    }
 
    const currentEnv = getClientEnvironment().stringified;
 
    if (pluginDefine) {
      pluginDefine.definitions = { ...pluginDefine.definitions, ...currentEnv };
    } else {
      cfg.plugins.push(new webpack.DefinePlugin(currentEnv));
    }
 
    return cfg;
  }
});

Then you can use these variables like:

    
let apiBaseUrl = process.env.SPFX_WEBAPI_BASEURL;

Reference: Using .env files in SharePoint Framework development

You can find full working code at: demo-spfx-dotenv


You can also use DefinePlugin for this. follow this: How To Handle Env Variable Using DefinePlugin In SPFx Solutions

1
  • Hi! I'm trying to set this up, but I'm still getting undefined for my environment variables. Do you know if there's anything special I may need to do if my WebParts are React components? Thank you!
    – hora
    Commented Aug 10, 2023 at 17:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.