@@ -15,6 +15,7 @@ export let shouldResetFactor: boolean;
15
15
let queueDirty : boolean ;
16
16
let preloadCount = 0 ;
17
17
const queue : BundleImport [ ] = [ ] ;
18
+ const MPA_FALLBACK_THRESHOLD = 100 ;
18
19
19
20
export const log = ( ...args : any [ ] ) => {
20
21
// eslint-disable-next-line no-console
@@ -203,7 +204,23 @@ export const adjustProbabilities = (
203
204
* too.
204
205
*/
205
206
let newInverseProbability : number ;
206
- if ( probability === 1 || ( probability >= 0.99 && depsCount < 100 ) ) {
207
+
208
+ /**
209
+ * 100 deps to be preloaded at once would mean a ~10s delay on chrome 3G throttling.
210
+ *
211
+ * This can happen for Link components as they load all of the route bundles at once, but in
212
+ * this case we fallback to MPA.
213
+ *
214
+ * This should never happen for a normal component. But in case it happens, we set the limit
215
+ * based on MPA_FALLBACK_THRESHOLD + 1 === 101 (to ensure the fallback works), because if the
216
+ * user has to wait for 10s before anything happens it is possible that they try to click on
217
+ * something else, in which case we don't want to block reprioritization of this new event
218
+ * bundles for too long. (If browsers supported aborting modulepreloads, we wouldn't have to
219
+ * do this.)
220
+ *
221
+ * TODO: Set the limit to a number of kb instead of a number of bundles.
222
+ */
223
+ if ( probability === 1 || ( probability >= 0.99 && depsCount <= MPA_FALLBACK_THRESHOLD + 1 ) ) {
207
224
depsCount ++ ;
208
225
// we're loaded at max probability, so elevate dynamic imports to 99% sure
209
226
newInverseProbability = Math . min ( 0.01 , 1 - dep . $importProbability$ ) ;
@@ -217,6 +234,8 @@ export const adjustProbabilities = (
217
234
dep . $factor$ = factor ;
218
235
}
219
236
237
+ dispatchMPAFallback ( ) ;
238
+
220
239
adjustProbabilities ( depBundle , newInverseProbability , seen ) ;
221
240
}
222
241
}
@@ -225,6 +244,7 @@ export const adjustProbabilities = (
225
244
export const handleBundle = ( name : string , inverseProbability : number ) => {
226
245
const bundle = getBundle ( name ) ;
227
246
if ( bundle && bundle . $inverseProbability$ > inverseProbability ) {
247
+ // prioritize the event bundles first
228
248
adjustProbabilities ( bundle , inverseProbability ) ;
229
249
}
230
250
} ;
@@ -267,3 +287,24 @@ if (isBrowser) {
267
287
}
268
288
} ) ;
269
289
}
290
+
291
+ /**
292
+ * On chrome 3G throttling, 10kb takes ~1s to download Bundles weight ~1kb on average, so 100
293
+ * bundles is ~100kb which takes ~10s to download.
294
+ *
295
+ * We want to fallback to MPA if more than 100 bundles are queued because MPA is always faster than
296
+ * ~10s (usually between 3-7s).
297
+ *
298
+ * Note: if the next route bundles have already been preloaded, the fallback won't be triggered.
299
+ *
300
+ * TODO: get total kb size and compare with 100kb instead of relying on the number of bundles.
301
+ */
302
+ const dispatchMPAFallback = ( ) => {
303
+ const nextRouteBundles = queue . filter ( ( item ) => item . $inverseProbability$ <= 0.1 ) ;
304
+ if ( nextRouteBundles . length >= MPA_FALLBACK_THRESHOLD ) {
305
+ const href = ( window as any ) . __qwikPendingFallbackHref ;
306
+ if ( href ) {
307
+ window . location . href = href ;
308
+ }
309
+ }
310
+ } ;
0 commit comments