(href: string, as: string, options?: ?PreloadImplOptions)
| 6307 | } |
| 6308 | |
| 6309 | function preload(href: string, as: string, options?: ?PreloadImplOptions) { |
| 6310 | const request = resolveRequest(); |
| 6311 | if (!request) { |
| 6312 | // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also |
| 6313 | // possibly get them from the stack if we are not in an async context. Since we were not able to resolve |
| 6314 | // the resources for this call in either case we opt to do nothing. We can consider making this a warning |
| 6315 | // but there may be times where calling a function outside of render is intentional (i.e. to warm up data |
| 6316 | // fetching) and we don't want to warn in those cases. |
| 6317 | previousDispatcher.L(/* preload */ href, as, options); |
| 6318 | return; |
| 6319 | } |
| 6320 | const resumableState = getResumableState(request); |
| 6321 | const renderState = getRenderState(request); |
| 6322 | if (as && href) { |
| 6323 | switch (as) { |
| 6324 | case 'image': { |
| 6325 | let imageSrcSet, imageSizes, fetchPriority; |
| 6326 | if (options) { |
| 6327 | imageSrcSet = options.imageSrcSet; |
| 6328 | imageSizes = options.imageSizes; |
| 6329 | fetchPriority = options.fetchPriority; |
| 6330 | } |
| 6331 | const key = getImageResourceKey(href, imageSrcSet, imageSizes); |
| 6332 | if (resumableState.imageResources.hasOwnProperty(key)) { |
| 6333 | // we can return if we already have this resource |
| 6334 | return; |
| 6335 | } |
| 6336 | resumableState.imageResources[key] = PRELOAD_NO_CREDS; |
| 6337 | |
| 6338 | const headers = renderState.headers; |
| 6339 | let header: string; |
| 6340 | if ( |
| 6341 | headers && |
| 6342 | headers.remainingCapacity > 0 && |
| 6343 | // browsers today don't support preloading responsive images from link headers so we bail out |
| 6344 | // if the img has srcset defined |
| 6345 | typeof imageSrcSet !== 'string' && |
| 6346 | // We only include high priority images in the link header |
| 6347 | fetchPriority === 'high' && |
| 6348 | // Compute the header since we might be able to fit it in the max length |
| 6349 | ((header = getPreloadAsHeader(href, as, options)), |
| 6350 | // We always consume the header length since once we find one header that doesn't fit |
| 6351 | // we assume all the rest won't as well. This is to avoid getting into a situation |
| 6352 | // where we have a very small remaining capacity but no headers will ever fit and we end |
| 6353 | // up constantly trying to see if the next resource might make it. In the future we can |
| 6354 | // make this behavior different between render and prerender since in the latter case |
| 6355 | // we are less sensitive to the current requests runtime per and more sensitive to maximizing |
| 6356 | // headers. |
| 6357 | (headers.remainingCapacity -= header.length + 2) >= 0) |
| 6358 | ) { |
| 6359 | // If we postpone in the shell we will still emit a preload as a header so we |
| 6360 | // track this to make sure we don't reset it. |
| 6361 | renderState.resets.image[key] = PRELOAD_NO_CREDS; |
| 6362 | if (headers.highImagePreloads) { |
| 6363 | headers.highImagePreloads += ', '; |
| 6364 | } |
| 6365 | // $FlowFixMe[unsafe-addition]: we assign header during the if condition |
| 6366 | headers.highImagePreloads += header; |
nothing calls this directly
no test coverage detected