Crank up auto import for dynamic Nuxt.js components
Auto import all the things 🚀
Back in the days we used to import all those components into every single .vue
file — import and registering them over and over again became a tedious task.
Then the awesome Nuxt.js team released @nuxt/components
to auto import project and third party library specific components 🚀 No more imports were necessary. No more component registering.
That’s it! Clean projects, clean components, clean webpack chunks.
That’s what I thought at least.
What about Headless CMS’s?
At our digital agency we have a bunch of projects using headless CMS’s — Storyblok as one among them. Storyblok gives the developer and the customer the freedom to nest components in all possible ways — dynamically.
So we wanted to load the components dynamically.
Nope.
That’s not possible at the time of this writing — at least not with @nuxt/components
out of the box (issue #43).
So I decided to dig some code — Let’s see how this Nuxt.js module works.
It looks like the module gets components based on what’s passed to the components:dirs
hook.
It prepares an array of components with their component names (PascalCase and kebab-case) and their relative filepaths.
In a second step all .vue
files will be scanned to load the components used in a given template (and to import those components). That’s why the auto import for a dynamic component does not work at all.
Back to the roots — import all those components manually? All of the 14328 possibilities?
No way!
Well then — Let’s try to figure out how we can solve that problem.
The underlying magic
Alright then: a dynamic component can be rendered if we pass a component name of an imported vue component or if we pass the component itself. Remember: @nuxt/components
is aware of every relative path for the auto importing mechanism. So if we could make dynamic webpack imports with those paths available inside a component we are able to load its children.
Plugin to the rescue
We are able to hook into the components:extend
hook and grab all the component names when we build a module.
Now we construct dynamic import statements for all components inside a plugin which injects the loaders into each vue component.
This translates to something like this:
That was an easy one, amirite?
Hydrate all the things
Now it’s possible to execute the injected async import to load a specific component — we will use vue-lazy-hydration
to do so (big thanks to Markus Oberlehner).
After executing the lazy import, the loaded component can be passed to the :is prop. NuxtDynamic
can now be used to auto import every dynamic component.
That’s it, we did it! Nuxt.js auto imports dynamic components 🚀
A clean and refined version of the outlined idea can be found on github and installed as npm package.
The official docs for @blokwise/dynamic
can be found at dynamic.blokwise.io.