-
-
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; | |
} |
Target is also a pretty generic term too - deploy target? Runtime target? Browser support target? Could mean a lot of different things.
True, we might want to rename target
to buildTarget
or similar 🤔 (for Next.js' current target
option that is)
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.
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.
@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.
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.
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.
What about having this feature in webpack itself? Like webpack.augmentConfig or something like that
Whether it's in webpack or not, webpack-merge seems like a good starting point.
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