GoogleChromeLabs / GoogleChromeLabs/quicklink

Prefetch returns `undefined` on slow connections

Open
#209 1 comment 3 reactions 0 assignees View on GitHub
help wanted
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).

![Capture d’écran 2020-11-26 à 16 32 15](https://user-images.githubusercontent.com/5370675/100369614-686ee580-3005-11eb-8a16-527c1dfcaadb.png)

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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.