How to change Nuxt module registration programmatically

Nuxt brings huge customization possibilities. This doesn't exclude its modules system, which can be customized programmatically, which is quite handy when using Nuxt's new layer feature.

Let's imagine the following situation: you have a base project which you use as a Nuxt layer in another project. In other words: your project (I'll call it the child project from now on) extends from your other project (which I'll call parent project). The parent project adds and registers a Nuxt module which is necessary in most of the projects that extend from the parent project. But our child project doesn't need the functionality the module provides. But since it's already registered in the config of the parent project, it is included in the final merged config of child and parent. So what now? 🤔

Nuxt hook 'modules:before'

Nuxt provides many hooks that you can use in modules and/or directly in the configuration file. The hook modules:before allows you to modify anything in the Nuxt application before the modules are installed. So it's a perfect fit for us to programmatically alter the module registration. 💪

To use it in the configuration you have to use the hooks config key. It can take an object with hierarchical structure of the hooks. So the hook modules:before becomes the following:

export default defineNuxtConfig({  hooks: {    modules: {      before(){        // Nuxt hook modules:before        // do your thing      }    }  },})

To get access to the Nuxt instance inside the hook there is the handy composable useNuxt from @nuxt/kit. We import it to use it inside our hook.
From the Nuxt instance we get access to all options from the configuration, including the modules to register. We can now alter these as we like and override the modules option with our desired result. In our example we remove a module that we do not want to be registered/installed.

// nuxt.config.jsimport { useNuxt } from '@nuxt/kit'export default defineNuxtConfig({  hooks: {    modules: {      before(){        const nuxt = useNuxt()        const { modules } = nuxt.options        const filteredModules = modules.filter((module) => {          if(typeof module === 'string'){            // Filter the module by name, @nuxt/image used as an example here            return module !== '@nuxt/image'          }          return true;        })        // Replace modules with our filtered modules        nuxt.options.modules = filteredModules;      }    }  }})

That's it, we have excluded a module that was registered in a layer we use for our project. 🥳
Of course you can use this method also for other things, for example reordering the modules if you want to achieve a specific order of installation.

It amazes me every time how extensible and well designed this framework is 🎉.