Overwriting definitions with multiple instances of DefinePlugin

Need

As a developer
I want to reduce duplication in my configs
So that they're more maintainable.

Deliverables

Given I have config A
And I have config B
And config A defines variable 'FOO' to be 'A'
And config B defines variable 'FOO' to be 'B'
And config B extends config A
When I load config B through webpack
Then 'FOO' will be injected with the value 'B'
// config A
module.exports = {
  plugins: [
    new DefinePlugin({FOO: 'A'})
  ]
};

// config B
var config = require('./a.config.js');
config.plugins.push(
  new DefinePlugin({FOO: 'B'})
);
module.exports = config;

The more practical use cases is having a production.config.js and a staging.config.js with the latter extending the former. I have a LOG_ERRORS variable defined in production.config.js to be false and I want to overwrite it in staging.config.js to be true.

The workaround I’m using now is to make sure the DefinePlugin instance is the last element in the plugins list in production.config.js and pop() it and replace it with another instance in staging.config.js. Not very future proof.

What I’d like is for newer instances of DefinePlugin in the plugins list to overwrite any definitions set by previous instances.

exports.plugins = [
  new DefinePlugin({FOO: 'A'}),
  new DefinePlugin({FOO: 'B'}),
  new DefinePlugin({FOO: 'C'})
];

// I expect `FOO` to be `C`.

Notes

I looked at lib/definePluggin.js and I saw that for every definition a compiler.parser callback is registered. I’m assuming that when the first callback is called and modifies the code, the rest of the callbacks won’t be called as the code doesn’t match them anymore.

I tried working out a solution where the callbacks request the latest definition of a key, but it required the assumption that the type of key (value, typeof etc) wouldn’t change between definitions (because different callbacks handle different types).

I’m more than happy to help with a PR if someone can point me in the right direction.

Author: Fantashit

1 thought on “Overwriting definitions with multiple instances of DefinePlugin

  1. Here’s my workaround:

            const runtimeGlobals = {
                    GOOGLE_ANALYTICS_ID: JSON.stringify(googleAnalyticsId),
            }
    
            ...
    
            if(isProduction) {
                    runtimeGlobals['process.env.NODE_ENV'] = JSON.stringify('production');
            }
    
            ...
    
            new webpack.DefinePlugin(runTimeGlobals),
    
    

    Don’t know how to split it into several files though.

Comments are closed.