graysonhicks / gatsby-plugin-loadable-components-ssr

Gatsby plugin for using @loadable/component with Gatsby's SSR
49 stars 26 forks source link

Loadable Components not prefetched on hover #43

Closed coreyward closed 2 years ago

coreyward commented 3 years ago

The default behavior of Gatsby Link is to prefetch Webpack chunks when a link is hovered over, which ensures they're available if/when that link is clicked. When using this plugin, however, loadable components are never prefetched. This results in a fair amount of layer shifting when navigating client-side, especially relative to the default approach without Loadable Components.

I tried to dive into this more, looking at webpack.stats.json, chunk-map.json, and the Loadable Components prefetch documentation, but I wasn't able to get anything working, and I still don't know how to “push” a dependency into the prefetched chunk list for a specific page (most of the chunk mapping appears to be template-specific, which doesn't work for most Loadable Components scenarios).

Any advice or support for this would be appreciated!

graysonhicks commented 3 years ago

Hi @coreyward, nice find! Yea, the chunk mapping file is a bit of a black box for me as well. I have a few v4 things I might need to add as well so will be looking at this in the next week or so.

coreyward commented 3 years ago

@graysonhicks Thanks for the response. We‘re still on Gatsby v2, so I’m hoping this is something that can be backported reasonably easily. 🤞 If so, I‘m happy to help test and sling some code if needed.

graysonhicks commented 3 years ago

Hi @coreyward so I had a few discussions with some other team members and this is more involved than it first appears. Essentially users have come to use loadable (and soon React.lazy) less for their lazy loading capability w/ Gatsby, and instead for code-splitting. So it is a bit like fighting upstream to undo the webpack behavior that is telling these chunks to load later in the process and maintaining SSR.

This plugin does it pretty darn well right now, but this (prefetching via Link) is still something it lacks. Adding on top that now with true SSR (non-SSG) in Gatsby, it will be hard to know whether a user is wanting to 'just code-split' or actually wants to lazy load with loadable or React.lazy, so adding custom handling of these async chunks to Gatsby core could have problems. So long term, I think what we are hoping to do is introduce a Gatsby API for doing those things that leverages something like loadable or React.lazy under the hood. e.g. import { createChunk } from 'gatsby'. Chunks created with that would have first-class support (ie. prefetching). Not sure this is high priority on the roadmap though.

Lastly, just using React 18 with this plugin should have performance improvements because the chunks should load earlier in the process. So this isn't a wont-fix but a will-fix-later 😄 .

coreyward commented 3 years ago

Interesting! I've been stubbing my toes on various approaches to code splitting with Gatsby and it seems like a lot of it comes back to the challenge you described. I haven't played with any of the v4 stuff, but without React 18 it doesn't seem like any of it helps with this anyways, right?

graysonhicks commented 3 years ago

Right, Gatsby 4 support React 18, but still not convinced React.lazy() makes the most sense long term. Right now this plugin is the best for code-splitting while maintaining SSR. React.lazy() will do that in a simpler way with React 18, but neither will support things like prefetching at the moment.

graysonhicks commented 2 years ago

Closing this with hopes it is answered at the framework level, not here in a plugin. For now, consider the flexibility of code-splitting the component as the tradeoff for losing the preload behavior. Also, there is already a lot of preloading of these chunks, just not on hover, so I think perf implications aren't too bad.

Still a very informative issue and thanks for filing @coreyward !