I am trying to set up Server Side Rendering with my meteor app that uses Apollo. I am getting the following error which I do not manage to solve (even following various post online -github and SO - and trying with different packages : unfetch, node-fetch...)

Error running template: Invariant Violation: 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.

For example: import fetch from 'node-fetch'; import { createHttpLink } from 'apollo-link-http';

Here is the code on the server side:

import fetch from 'node-fetch';
import { Accounts } from 'meteor/accounts-base';
import { Meteor } from 'meteor/meteor';
import { onPageLoad } from 'meteor/server-render';
import { StaticRouter } from 'react-router-dom';
import { renderToString } from 'react-dom/server';
import React from 'react';
import { routes } from './../both/router';
import Menu from './../../ui/Menu';
import { ApolloProvider } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import { createHttpLink } from 'apollo-link-http'    
import './apollo'; // THIS IS THE APOLLO SERVER CODE

onPageLoad((sink) => {
    let App = props => (
        <StaticRouter location={props.location}>
            {routes}
        </StaticRouter>
    )

    const client = new ApolloClient({
    ssrMode: true,
    link: createHttpLink({
      uri: '/graphql',
      credentials: 'same-origin',
      headers: {
        cookie: sink.request.cookies,
      },
        }),
        fetch: fetch,
    cache: new InMemoryCache(),
  });

    let AppToRender = props => (
        <ApolloProvider client={client}>
            <App />
        </ApolloProvider>
    )

     sink.renderIntoElementById('app', renderToString(<AppToRender location={sink.request.url} />));

});

I also tried Apollo-Client from apollo-boost and it didn't work either. Would very much appreciate if someone could help with the issue.

1 Answers

1
Ivo On Best Solutions

After reinstalling and removing three more times unfetch and node-fetch and importing them everywhere I found out that during my test I once also moved the "fetch: fetch" outside of the createHttpLink but still inside the new Apollo-Client on client side.

Finally it works with the following imports :

import fetch from 'unfetch';
import React from 'react';
import { Accounts } from 'meteor/accounts-base';
import { Meteor } from 'meteor/meteor';
import { onPageLoad } from 'meteor/server-render';
import { StaticRouter } from 'react-router-dom';
import { renderToString } from 'react-dom/server';
import { routes } from './../both/router';
import { ApolloProvider } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import { createHttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';

import Menu from './../../ui/Menu';

import './email-templates';
import './apollo';
import './users';

and the following creation of the Apollo Client on server side for SSR :

onPageLoad((sink) => {
    let App = props => (
        <StaticRouter location={props.location}>
            {routes}
        </StaticRouter>
    )

    const client = new ApolloClient({
       ssrMode: true,
       link: createHttpLink({
         uri: '/graphql',
         credentials: 'same-origin',
         headers: {
           cookie: sink.request.cookies,
         },
         fetch: fetch,
       }),
       cache: new InMemoryCache(),
    });

    let AppToRender = props => (
        <ApolloProvider client={client}>
            <Menu />
            <App />
        </ApolloProvider>
    )

     sink.renderIntoElementById('app', renderToString(<AppToRender location={sink.request.url} />));

});

Have to admit the indentation on S.O. didn't show well which was harder to solve my issue but it was fine in my project. I tried so many different things that I forgot to go back from start in the creation of the Apollo Client.