Skip to content

Instantly share code, notes, and snippets.

@developit
Created January 2, 2019 13:49
Show Gist options
  • Save developit/ea457f2e01b5e300c2b749d788a13b09 to your computer and use it in GitHub Desktop.
Save developit/ea457f2e01b5e300c2b749d788a13b09 to your computer and use it in GitHub Desktop.
export function loadConfigModule(filename) {
// sub your own
return require(filename);
}
/**
* Modify a Webpack configuration by applying a mutator module/function.
* @param {Object} options
* @param {Object} options.config Webpack configuration object to modify in-place
* @param {Object} options.module A configuration function of the form `(config, env)=>`,
* or an Object with a `webpack` method of that form.
* @param {String} [options.target] "client" for browser bundles, "server" for Node/SSR/prerendering
* @param {Boolean} [options.production] Defaults to `process.env.NODE_ENV==='production'`
* @param {Boolean} [options.watch] Whether the bundle is being built for HMR/watch usage
* @param {Object} [options.env] Environment values to expose as options to the config function
* @param {Object} [options.helpers] Utility functions to pass as a 3rd arg to the config function
* Example: github.com/developit/preact-cli/blob/master/src/lib/webpack/transform-config.js#L29
*/
export function modifyConfig({
config,
module,
target = 'client',
production = process.env.NODE_ENV === 'production',
watch = false,
env = {},
helpers = {}
}) {
const webpackMutator = module.webpack || module;
if (typeof webpackMutator !== 'function') {
throw Error(`Webpack configuration plugin must be a function of the form (config, { target }) => void`);
}
const ssr = target === 'server';
const options = {
production,
watch,
target,
...env,
// Compat aliasdes for Next.js, Preact CLI, etc
ssr,
isProd: production,
isWatch: watch,
isServer: ssr,
};
webpackMutator(config, options, helpers);
return config;
}
@timneutkens
Copy link

Sounds like a great idea! However with regards to naming target might cause confusion in the context of Next.js because of: vercel/next.js#5927

@developit
Copy link
Author

Target is also a pretty generic term too - deploy target? Runtime target? Browser support target? Could mean a lot of different things.

@timneutkens
Copy link

timneutkens commented Jan 2, 2019

True, we might want to rename target to buildTarget or similar 🤔 (for Next.js' current target option that is)

@kentcdodds
Copy link

I wonder if you all would consider doing something like this:

// webpack.config.js
const baseConfig = require('preact-cli/webpack')

// I'm responsible for merging/manipulating the
// base config with my own modifications
module.exports = {}

This is how kcd-scripts and paypal-scripts both work https://blog.kentcdodds.com/concerning-toolkits-4db57296e1c3

I'm really happy with this solution because it means that finding the config is obvious and other tools that interact with that config (editor plugins or testing/linting frameworks) can find the config without any additional configuration needed.

@timneutkens
Copy link

The problem for that with Next.js for example is that it's not "just one config" it's actually 2 configs, one for client compilation and one for server compilation.

@developit
Copy link
Author

@kentcdodds @timneutkens yup, same deal with Preact CLI (one for client, one for prerendering/ssr). Also there's the issue of nested configuration modifiers (~plugins).

Webpack Blocks had an interesting approach, which basically allowed merging multiple subsets of webpack configuration into their sum using logic that was aware of the config schema.

@kentcdodds
Copy link

I've had that problem as well. I solved that by overloading the env argument:

// fullEnv could be any combination of:
// development:client
// production:server
// or even simply: "development" and it should still work
module.exports = (fullEnv) => {
  const [env, subenv = 'client'] = fullEnv.split(':')
}

It's a bit less straightforward 😬, but I thought it was worth it.

@kentcdodds
Copy link

Also there's the issue of nested configuration modifiers (~plugins).

True, it's an annoying problem. Typically what I do is I filter out the plugins I want to change and add my own version of those plugins. But this is a problem regardless of what API you come up with.

@kandros
Copy link

kandros commented Jan 2, 2019

What about having this feature in webpack itself? Like webpack.augmentConfig or something like that

@willhoney7
Copy link

Whether it's in webpack or not, webpack-merge seems like a good starting point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment