-
Notifications
You must be signed in to change notification settings - Fork 4.6k
fix: use the native fetch
API in browsers and a patched node-fetch
otherwise
#25576
fix: use the native fetch
API in browsers and a patched node-fetch
otherwise
#25576
Conversation
@@ -0,0 +1 @@ | |||
export default globalThis.fetch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
globalThis
will resolve to self
in workers, and window
in browsers. Both have fetch
available on them.
Aside.. @steveluscher what version of yarn do you use? I'm on 1.22.18 and I think we keep thrashing the lock file and creating huge diffs. Can we try to get on the same version? |
Codecov Report
@@ Coverage Diff @@
## master #25576 +/- ##
===========================================
- Coverage 82.0% 75.3% -6.7%
===========================================
Files 655 40 -615
Lines 171822 2342 -169480
Branches 335 336 +1
===========================================
- Hits 140972 1765 -139207
+ Misses 30734 459 -30275
- Partials 116 118 +2 |
I'm on 1.22.17. 🤔 |
Maybe it's dependabot then 🤷🏻 |
That little point version made all the difference! I just upgraded to 1.22.19 and now the diff is many times smaller. |
fetch
API in browsers and a patched node-fetch
otherwise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm but have a few questions.. and I think the typing magic you used is cool but hard to understand and maintain. I'd prefer if things were simpler.
init?: nodeFetch.RequestInit, | ||
): Promise<nodeFetch.Response> { | ||
const processedInput = | ||
typeof input === 'string' && input.slice(0, 2) === '//' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when would the input be missing a protocol and just start with //
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a standard patch for the broken implementation of node-fetch
that doesn't support protocol-relative URLs like the fetch
in browsers does. https://github.com/node-fetch/node-fetch/blob/main/docs/v2-LIMITS.md
Folks can and will write apps that make use of protocol-relative URLs, and we don't want them to break in Node when they do.
This replicates what cross-fetch
was already doing.
web3.js/src/connection.ts
Outdated
fetchMiddleware?: FetchMiddleware, | ||
disableRetryOnRateLimit?: boolean, | ||
): RpcClient { | ||
const fetch = customFetch ? customFetch : crossFetch; | ||
const fetchImpl = (customFetch ? customFetch : fetch) as FetchFn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: how about importing ./fetch-iml
as fetchImpl
and keeping this as fetch
?
web3.js/src/connection.ts
Outdated
) => any | ||
? (...args: A) => TReturn | ||
: never; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't really make sense of this syntax.. what is being evaluated by the ?
operator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. I was hoping the names of the utility types would make the reader incurious as to how it's implemented. These types should really just be TypeScript builtins, but alas.
I'll kill this stuff and just write the types manually.
web3.js/src/connection.ts
Outdated
export type FetchMiddleware = AlterReturnType< | ||
AddParameters<FetchFn, [fetch: AlterReturnType<FetchFn, void>]>, | ||
void | ||
>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the benefit of expressing the type of FetchMiddleware
like this over the original type signature which is more explicit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the original signature is just straight up wrong. The first parameter to fetch
is RequestInfo
not string
. The second RequestInit
not any
. I'm just trying to make everything properly line up with the type of the fetch-impl
shim.
Problem
cross-fetch
is incompatible in that environment.fetch
ponyfill when in reality web3.js is already incompatible with browsers that don't supportfetch
natively.Summary of Changes
globalThis.fetch
which works in browser and Service Worker environments.Notes on the new fork system
The fork system (which should really have been in a separate PR) lets you override modules depending on the build environment. Given that you have a module called
foo
, the build system will check if there's a module at that directory level called__forks__/CONFIG/foo.ts
. If there is, that will be built into the bundle.Test plan
Ran the test plan at https://github.com/wentokay/unfetch-test. Thanks @wentokay!
Noted that this saves 2.62K gzipped (tested in Solana Explorer build).
This diff was inspired by the phenomenal PR #25500.