GoogleChromeLabs / GoogleChromeLabs/quicklink
Prefetch returns `undefined` on slow connections
- Dominant language
- JavaScript
- Stars
- 11.3k
- Forks
- 429
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the bug**
I'm running an app that uses `prefetch` while throttling the network ("Slow 3G" mode on Chrome). When doing so, `prefetch(url)` returns `undefined` instead of a Promise.
When the network is throttled on "Slow 3G", the output of `navigator.connection` is as follows:
```js
navigator.connection.effectiveType // "2g"
navigator.connection.saveData // false
```
Given the [precondition](https://github.com/GoogleChromeLabs/quicklink/blob/master/src/index.mjs#L119-L127) in the `prefetch` function, [the function should return a rejected promise](https://github.com/GoogleChromeLabs/quicklink/blob/master/src/index.mjs#L125). However, it looks like in the production bundle, both `Promise.reject` statements are gone.
Here's a (beautified) snapshot of the relevant code chunk in the shipped `quicklink.js` from my `node_modules`:
```js
function i(e, r, i) {
if (!(i = navigator.connection) || !i.saveData && !/2g/.test(i.effectiveType)) return Promise.all([].concat(e).map(function(e) {
if (!o.has(e)) return o.add(e), (r ? function(e) {
return window.fetch ? fetch(e, {
credentials: "include"
}) : n(e)
} : t)(new URL(e, location.href).toString())
}))
}
```
So, in my case described above, we're not going into that `if` statement, and the function implicitly returns `undefined`. When chaining `prefetch(url)` with `catch`, this raises a runtime error.
I saw that the library uses [`microbundle`](https://github.com/developit/microbundle), which I'm not familiar with, so I'm not aware of stripping behavior. At first glance, no apparent options seem to remove such code.
**To Reproduce**
1. Go to [this sandbox](https://codesandbox.io/s/currying-shadow-vk8bz?file=/src/index.js) on Chrome (or a browser that supports the [Network Information API](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation) and lets you throttle the network).
2. Switch the connection to "Slow 3G" and refresh.
3. See the logged `undefined` in the browser console.
**Expected behavior**
I'd expect `prefetch` always to return a Promise, [as documented](https://github.com/GoogleChromeLabs/quicklink#quicklinkprefetchurls-ispriority).
**Version:**
- macOS Catalina 10.15.7
- Chrome 85.0.4183.121 with throttled network ("Slow 3G")
**Additional context, screenshots, screencasts**
Here's a screenshot of the [linked sandbox](https://codesandbox.io/s/currying-shadow-vk8bz?file=/src/index.js).

Once the root cause of the missing code is identified, it could be a nice improvement to also run tests in a slow environment. Since the project already uses Puppeteer, it should be able to interact with Chrome DevTool's `Network.emulateNetworkConditions` and change the latency and network throughput.
Contributor guide
Research direction
Start in src/index.mjs around the precondition at lines 119-127 and compare it with the shipped quicklink.js bundle shown in the report. Investigate the microbundle output and the existing Puppeteer tests, then verify that prefetch returns a Promise under throttled network conditions and add coverage for that case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- build-system, performance
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100