# Middleware The basic unit of interacting with Neutrino is middleware. In Neutrino, middleware are functions that are provided a Neutrino instance for the intent of modifying configuration, listening for events, getting build metadata, or augmenting with custom functionality. At its simplest, a middleware function accepts a Neutrino instance argument and does nothing: ```js function middleware(neutrino) {} ``` A middleware function can also optionally accept an `options` argument which will be fed back into the middleware function when used. ```js function middleware(neutrino, options) {} ``` The signature of this function is what we call "Neutrino middleware". If you're familiar with middleware from the Express/connect world, this works similarly. When using Express middleware, you provide a function to Express which receives arguments to modify a request or response along its lifecycle. There can be a number of middleware functions that Express can load, each one potentially modifying a request or response in succession. Neutrino will execute middleware similarly, where each middleware function successively interacts with Neutrino along the lifecycle. This is done by plugging in the middleware to Neutrino via the `use()` method. ```js const api = new Neutrino(); api.use(middleware); api.use(middleware, options); ``` To use a concrete example, let's create middleware that adds an environment plugin: ```js const { Neutrino } = require('neutrino'); const { EnvironmentPlugin } = require('webpack'); const api = Neutrino(); function env(neutrino, additionalVars = []) { neutrino.config .plugin('env') .use(EnvironmentPlugin, ['NODE_ENV', ...additionalVars]); } api.use(env); // or: api.use(env, ['SECRET_KEY']); ``` ## Loading middleware Additional middleware can also be loaded from a middleware function. This makes their composition simpler for consumers. ```js // neutrino-middleware-env const { EnvironmentPlugin } = require('webpack'); module.exports = (neutrino, additionalVars = []) => neutrino.config .plugin('env') .use(EnvironmentPlugin, ['NODE_ENV', ...additionalVars]); ``` ```js // react preset (which is also middleware) const env = require('./neutrino-middleware-env'); module.exports = neutrino => { neutrino.use(env, ['SECRET_KEY']); neutrino.use(/* next middleware */); neutrino.use(/* next middleware */) }; ``` ## Configuring If your middleware requires configuration _outside_ of the options necessary for _running_ the middleware, use a closure technique for simplifying this for your middleware consumers. In short, your module will provide a function to consumers which, when executed, will return a Neutrino middleware function. Describing this in code: ```js module.exports = function wrapper(...args) { return function middleware(neutrino, options) { // do something with neutrino, options, and args }; }; ``` Let's create a contrived example using our `env` middleware. Let's use a closure to let the consumer provide an alternate plugin name when creating the middleware: ```js // neutrino-middleware-env const { EnvironmentPlugin } = require('webpack'); module.exports = (pluginName = 'env') => (neutrino, additionalVars = []) => { neutrino.config .plugin(pluginName) .use(EnvironmentPlugin, ['NODE_ENV', ...additionalVars]); }; ``` ```js // react preset (which is also middleware) const env = require('./neutrino-middleware-env'); module.exports = neutrino => { neutrino.use(env('ENV-PLUGIN'), ['SECRET_KEY']); }; ``` ## Distributing If you would like your middleware to be used by others, feel free to publish and distribute! By putting your middleware on npm, GitHub, or another location, you can share the hard work put into abstracting away Neutrino and Webpack interactions and save everyone in the community time and effort. As long as the Neutrino CLI, other middleware, or presets can require your middleware, it puts no restrictions on where you want to host it. ## Core middleware Neutrino maintains a number of core middleware packages which aid in creating the various preset packages we also distribute. Continue onward for documentation on these various middleware packages.