Description
The Problem
In Nuxt components v2, components are dynamically imported with async. This change was a nightmare for me because it result in several issues which took the better part of several days to find the cause of.
Hard to Find Bug Resulting from the Problem
Here is the issue I had created on the Nuxt repository the first time I ran into the problem:
nuxt/nuxt#8981
The solution required me to write extra code in my custom component because I needed to ensure that $el
existed before I could initialize a gsap
animation. It was very counter-intuitive for me to not be able to assume that $el
was populated inside of the mounted()
hook, instead having to write a conditional inside the updated()
hook to check if the element was populated each time. Honestly not a great solution in my opinion.
Also, this only broke I after I upgraded to v2 of Nuxt components, and unfortunately the migration guide was of no help to me because it didn't explain that components being automatically made global also meant they were being imported dynamically. I was totally in the dark on that detail.
Another Different Hard to Find Bug Resulting from the Problem
Today I just ran into another problem which I eventually discovered was resulting from async component loading. This time, my styling broke because I relied on the assumption that an id
attribute would be present, but it wasn't due to this same async component loading. Nothing about this behavior was intuitive to me.
Here is a simple Code Sandbox that shows the second problem in action:
https://codesandbox.io/s/boring-bassi-et0fb?file=/layouts/default.vue
What I'd Like to See
Documentation for Effects of Async Component Loading
First, we need a clear part of the documentation that explains the downsides of the async component loading so people don't spend hours trying to debug the source of weird issues. I imagine that 99% of Vue users expect $el
to always exist in the mounted()
hook, and id
attributes to never disappear without a clear cause. Any behavior that changes this makes for a very dangerous default, in my humble opinion.
Official Support for loader: true
In the issue I linked above, @pi0 revealed that we can set loader: true
to re-enable v1 behavior. However, he also stated that this is "not recommended nor guaranteed to always work". I propose that this solution be made officially supported for those who wish to not lose sleep at night.
Somewhere in nuxt.config.js
to Exclude Specific Components from Async Loading
Additionally, provide a way to list components in nuxt.config.js
that should not be loaded in an async manner.
Why not just import
components manually? Random importing certain components here and there in a codebase to force them to not be loaded async is confusing, because there is not immediately any apparent reason why one component is manually imported and another isn't, unless clear comments are left. Anyone could remove the component import thinking they are just cleaning things up and end up breaking the application. Also, manually importing components defeats part of what I love about Nuxt components, which is cleaner code due to not having to import them manually.
TL;DR / Summary
- Clearly document the behavior changes when using async components. Even if this is just a link to some existing Vue documentation for what happens when you use async components, it would be extremely helpful because I'll bet a lot of more serious users are running into issues resulting from async component loading as a default and scratching their heads.
- Provide an officially supported way to not use async components. I understand why you guys started using them, but I've already run into two situations where they make things harder instead of easier, and I'm willing to bet many others have as well.
- Make using
loader: true
officially supported, rename it toasync: false
or something like that so it's clear what it does, and document how and when to use it. - Provide a property with the name
staticComponents
orexcludeAsync
something like that where paths to components or maybe even entire directories of components can be specified to be excluded from being loaded dynamically with async.
- Make using
Bottom line, let's not force people to stop using the mounted()
hook or manually import components (negating the benefit of Nuxt components) to make initial component state consistent in their applications.
Thanks so much for your hard work on Nuxt, and I appreciate your consideration of my suggestion.