Potential change to support `lazy` with SSR

Author: sidhu663Created Jul 26, 2025Updated Jul 26, 2025

Apologies if this is the wrong section for this but I'd like to help support lazy(...) with SSR. All the pieces seem to work fine as is

  • chunkextractor collects the used chunks
  • loadableReady on the client correctly preloads all the required scripts

except that when using lazy, it always throws the loadAsync promise on first render. This causes a suspense boundary to trigger even though technically the module is available and loaded. I took a quick look at the code and have a potential fix.

I wanted to get a gut-check on if this is a sensible approach. If so, I can make a more concrete PR. Basically, try to load sync and if the module is available, don't throw the promise. I've tested this with my setup and it works as desired: renders the full content during SSR and hydrates correctly without any flashing

diff
diff --git a/packages/component/src/createLoadable.js b/packages/component/src/createLoadable.js
index 5a3da83..46d82cd 100644
--- a/packages/component/src/createLoadable.js
+++ b/packages/component/src/createLoadable.js
@@ -92,6 +92,18 @@ function createLoadable({
       const cacheKey = getCacheKey(props)
       let promise = cache[cacheKey]
 
+      if (!promise) {
+        try {
+          promise = Promise.resolve(ctor.requireSync(props))
+          promise.status = STATUS_RESOLVED
+          cache[cacheKey] = promise
+          return promise
+        } catch (e) {
+          // We didn't find the module synchronously, so we continue
+          // to load it asynchronously
+        }
+      }
+
       if (!promise || promise.status === STATUS_REJECTED) {
         promise = ctor.requireAsync(props)
         promise.status = STATUS_PENDING

Source: gregberge/loadable-components