Intended outcome:
execute normally in node environment.
Actual outcome:
throw error:
fetch is not found globally and no fetcher passed, to fix pass a fetch for
your environment like https://www.npmjs.com/package/node-fetch.
How to reproduce the issue:
// create a new ts project and typings follow
import gql from 'graphql-tag';
import ApolloClient from 'apollo-boost';
import fetch from 'node-fetch';
const uri = 'https://w5xlvm3vzz.lp.gql.zone/graphql';
const client = new ApolloClient({
uri,
fetchOptions: {
fetch: fetch as any
}
});
client
.query({
query: gql`
{
rates(currency: "USD") {
currency
}
}
`
})
.then(result => console.log(result));
execute:
ts-node src/index.ts
Versions
"dependencies": {
"apollo-boost": "^0.1.8",
"graphql": "^0.13.2",
"graphql-tag": "^2.9.2",
"node-fetch": "^2.1.2",
"react-apollo": "^2.1.4"
},
"devDependencies": {
"@types/node-fetch": "^2.1.1"
}
code error
it seems that is a code error in apollo-boost.in
apollo-boost/src/index.ts,DefaultClientcall new HttpLink(xxx) to create a HttpLink:const httpLink = new HttpLink({ uri: uri || '/graphql', fetchOptions: fetchOptions || {}, credentials: credentials || 'same-origin', headers: headers || {}, });and
HttpLinkis defined inapollo-link-http, which callscreateHttpLink:export class HttpLink extends ApolloLink { public requester: RequestHandler; constructor(opts?: HttpLink.Options) { super(createHttpLink(opts).request); } }in
createHttpLinkit will access fetch in param:export const createHttpLink = (linkOptions: HttpLink.Options = {}) => { let { uri = '/graphql', // use default global fetch is nothing passed in fetch: fetcher, includeExtensions, useGETForQueries, ...requestOptions } = linkOptions; // dev warnings to ensure fetch is present checkFetcher(fetcher); // omit other code }
fetchdoes exists inlinkOptionsbut exists inlinkOptions.fetchOptions, sofetcheris undefined ans callcheckFetcher(fetcher);throws error.
Thanks @forclan - this is actually working as designed, but it is definitely a bit confusing. Apollo Boost doesn't let you set a fetch (as you've found out, passing one in via fetchOptions won't work). For now your best bet is to eject from apollo-boost, and use the full apollo-client instead. Then when you define your HttpLink, you can properly set the fetch option.
I've marked this as a bug though since apollo-boost should work on the server, and allow a custom fetcher to be defined. If anyone is interested in adjusting boost to accept a fetch param, which will the be passed into the HttpLink instance, that would be awesome!
@hwillson I'm happy to take that one. Just tell me, the current behaviour is expected (in the browser) but you're suggesting to add fetch as a param to ApolloBoost then should I somehow check if we're running it in the browser/node.js environment and only allow it on node.js env or just simply add fetch param regardless of environment?
Sorry for the delay @mbaranovski - I meant add the fetch param regardless (which you've done in your PR). Thanks!
I'will close the issue since code is merged.
@hwillson Do we have to specify the fetch param? Can't we just use a global unfetch polyfill
@borisyordanov unfetch is for js in browser, there we use it. In node.js, we need to pass a fetch lib like node-fetch.
Most helpful comment
Thanks @forclan - this is actually working as designed, but it is definitely a bit confusing. Apollo Boost doesn't let you set a
fetch(as you've found out, passing one in viafetchOptionswon't work). For now your best bet is to eject fromapollo-boost, and use the fullapollo-clientinstead. Then when you define yourHttpLink, you can properly set thefetchoption.I've marked this as a bug though since
apollo-boostshould work on the server, and allow a custom fetcher to be defined. If anyone is interested in adjusting boost to accept afetchparam, which will the be passed into theHttpLinkinstance, that would be awesome!