Read and manipulate SPFx configuration values in your code like a boss

Basics

SPFx has a built-in mechanism, which holds some configuration values for you. For example in runtime, you can read them and determine if you are running locally or not. You can verify if you are in debug mode or not. You can do some other things as well. Let’s take a closer look at some values, available out-of-the box.

Probably you know, that SPFx build pipeline is webpack based. It means, that webpack’s configuration supplies a lot of those values. The most useful are:

  • process.env.NODE_ENV - can be either ‘production’ or ‘dev’ depending on an environment where the code is running
  • DEBUG – boolean, equals to false for release builds and true for development
  • DATACENTER – boolean, equals to true if you are running in context of SharePoint Online. Might be useful if you build webparts for on-prem and Online at the same time

NOTE : in order process.env.NODE_ENV to be available and compiled in your code without errors, you should install type definitions for node:

npm install @types/node --save-dev

Additionally, you should update tsconfig.json and add “node” value under “types” array.

To have your code compiled with other variables, you should explicitly add declarations for them like below (in any of your .ts source files):

declare var DATACENTER: string;
declare var DEBUG: string;

If you want to determine SharePoint page type you are running on, you should use code based approach. Consider the code below, which is pretty self-explanatory:

import { Environment, EnvironmentType } from '@microsoft/sp-core-library';

if (Environment.type == EnvironmentType.ClassicSharePoint) {
      // code for classic SharePoint here
    } else if (Environment.type === EnvironmentType.SharePoint) {
      // code for modern SharePoint here
    } else if (Environment.type === EnvironmentType.Local) {
      // you are running locally here
    } else if (Environment.type === EnvironmentType.Test) {
      // you are running tests
    }

In some cases this should be sufficient, however for big applications you might need more control over configuration values. Let’s go to advanced section.

Advanced

As was mentioned earlier, SPFx build pipeline is webpack based. Microsoft provides a lot of ways to customize the pipeline, including webpack step. That’s something we’re going to do.

Imagine a very common scenario, when you need to inject remote API url into your SPFx webpart. The url is different for production and local development. Of course, we can do that with if (DEBUG) statements, however it doesn’t look good in code and doesn’t scale to other requirements you might have in future. That’s why we will go with advanced approach.

First of all, you should install webpack-merge module. It merges different webpack configs.

npm install webpack-merge --save-dev

Next step is to insert below code in your gulpfile.js:

const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
const merge = require('webpack-merge');
const webpack = require('webpack');
build.addSuppression(/Warning - \[sass\] The local CSS class .* is not camelCase and will not be type-safe/gi);

build.configureWebpack.setConfig({
    additionalConfiguration: function (config) {
        let isDevelopment = process.env.NODE_ENV === 'DEVELOPMENT';
        let defineOptions;
        if (isDevelopment) {
            console.log('***********    Applying development settings to webpack *********************');
            defineOptions = {
                '_AzureHostUrl_': JSON.stringify('https://localhost:8810/')
            }
        } else {
            // specify production keys here
            defineOptions = {
                '_AzureHostUrl_': JSON.stringify('https://your-real-api.com/')
            }
        }

        return merge(config, {
            plugins: [
                new webpack.DefinePlugin(defineOptions)
            ]
        });
    }
});

build.initialize(gulp);

We modified our gulpfile to update webpack config with an additional plugin. This plugin called DefinePlugin. It dynamically injects values into your code. For development environment ( isDevelopment = true ) we use one url and another one for production. You can set different nodejs environmental variables using npm scripts and cross-env nodejs module. Install cross-env module and add new script in your package.json, under scripts section:

"serve": "cross-env NODE_ENV=DEVELOPMENT gulp serve"

By running npm run serve  you will have your local API url available in your code. When packaging your application, it uses production url, because it that case NODE_ENV will be equal to Production. You can store a lot of configuration variables that way.

You can go further and create helper convenient class to manage your configuration:

declare var _AzureHostUrl_: string;

export class HostSettings {
    public static get AzureHost(): string {
        return _AzureHostUrl_;
    }
}

Later in code you can use it that way:

http.get(`${HostSettings.AzureHost}api/...`)

Conclusion

SPFx gives you different options for configuring runtime values. You can rely on values provided OOB by SPFx build pipeline or you can implement custom provider by modifying the pipeline. While the second approach looks a bit more complicated, it gives you a lot more flexibility, control and scalability over your webpart’s configuration.