webpackwebpack-loader

How can I evaluate a Node script during a Webpack build and make it contents available to the compiled code?


I have a Node script that uses fs.readFileSync several times to read various JSON5 configuration files that exist on the filesystem. These are read in, combined, manipulated, appended to, etc. based on certain criteria in the ENV variables. The output of this file is a JavaScript object via module.exports.

I would like this script to be evaluated each time I run my Webpack build process and the output JS object made available in the bundle, so when my client React scripts do import { foo, bar } from 'config';, those values can be accessed by the client code.

This seems like something that would a loader would solve, but I have been unable to get any of them working.

How can I evaluate a Node script during Webpack compile time and make its export be available to the compiled client code?


Solution

  • As I said in a comment on your question the idiomatic way to handle config in webpack is with DefinePlugin, so in your case that would mean doing the configuration processing within your webpack config. Webpack would then handle interpolation of your config variables in-place automatically and you would not need to bring in config using an import statement. Something like:

    // webpack.config.js
    const webpack = require("webpack");
    const config = require("./process-config")
    
    module.exports = {
      // ...
      plugins: [
        webpack.DefinePlugin({
          config
        })
      ]
    };
    
    // app.js
    if (config.SOME_CONFIG_VAR) {
      // do work when SOME_CONFIG_VAR=true
    }
    

    Having said that, another way more in tune with what you're looking for might be to use the val-loader which is a loader that

    executes a given module, and returns the result of the execution at build-time, when the module is required in the bundle

    [ source ]

    Using val-loader might look something like:

    // webpack.config.js
    module.exports = {
      // ...
      module: {
        rules: [
          {
            test: /config.js$/,
            use: [{ loader: "val-loader" }]
          }
        ]
      }
    }
    
    // config.js
    const config = require("./process-config.js");
    const JSON = require("json5");
    
    module.exports = {
      code: `module.exports = "${JSON.stringify(config)}"`
    }
    
    // app.js
    const config = require("./config.js");
    
    if (config.SOME_CONFIG_VAR) {
      // do work when SOME_CONFIG_VAR is truthy
    }