'webpack try to require a module that might be missing

I want to try to require a module in a webpack build and if that file is not found just do nothing, don't throw an error etc.

I tried doing it this way:

try {
  const local = require('./config-local.js');
  extend(config, local);
} catch (err) {
  // do nothing here
}

Basically what I want to do is to extend a config object with a local config if that file is found but if it isn't just don't extend it with anything.

Webpack throws an error that module is missing even though that require is wrapped in a try/catch clause.

How to tell webpack to ignore it?



Solution 1:[1]

Based on @trysis comment, I ended up doing this in my project:

const REQUIRE_TERMINATOR = '';
try {
  const local = require(`./config-local.js${REQUIRE_TERMINATOR}`);
  extend(config, local);
} catch (err) {
  // do nothing here
}

This will give WebPack enough information to include all files starting with config-local.js (which will be exactly the file you want), but also confuse it enough that it won't try to verify file's existence ahead of time, so your try/catch block will trigger during runtime.

Solution 2:[2]

Webpack tries to bundle each one of your require into the output file. It does a static analysis finds a require and tries to read it. Your try&catch will work only in runtime.

All you need to do is to “mark” this require as special.

You can do it by using webpack’s special require: __ webpack_require__ which won't be parsed at build time, and will become a regular require in the bundle.

try {
  const local = __webpack_require__('./config-local.js');
  extend(config, local);
} catch (err) {
  // do nothing here
}

Solution 3:[3]

I think a slightly different approach might give you the result you want. You mention that the file in question is application config; I would handle this in webpack.config.js rather than in the application code. There your require will follow ordinary nodeJS rules rather than webpack's static analysis. You can try/catch the require statement and land on the resulting config that the app will use, then inject that config into the app using the DefinePlugin. IMO using DefinePlugin (with data from a static file or env variables) like this is a more common pattern for injecting config into a webpack-built application.

// load config data
const defaultConfig = require("default-config.json");
let localConfig = {};
try {
  localConfig = require("config-that-may-not-exist.json");
} catch (err) {}

const actualConfig = Object.assign(defaultConfig, localConfig);

// ...later, in plugins part of config:
plugins: [
  new webpack.DefinePlugin(actualConfig)
]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 panta82
Solution 2
Solution 3 Brendan Gannon