Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Amplitude with SSR (React) #110

Closed
adrienharnay opened this issue Jul 20, 2017 · 5 comments
Closed

Using Amplitude with SSR (React) #110

adrienharnay opened this issue Jul 20, 2017 · 5 comments

Comments

@adrienharnay
Copy link

Hi,

I am trying to migrate a codebase from client-side to server-side, and am using Amplitude like so:

import amplitude from 'amplitude-js/amplitude';

It is bundled by Webpack. On the server-side, I have this error:

document is not defined, l.3020, called by global scope block l.3007

I'm a bit lost on this, as there is browser-specific code in global scope and therefore it can't run on server...

Any insights?

Thanks in advance

@blazzy
Copy link
Contributor

blazzy commented Sep 13, 2017

Hi @Zephir77167, The SDK currently does not work in node/server-side environments. We do have improvements planned to address this, but they will likely be a while.

In the mean time you may be able to work around this with a conditional require for your server side build.

@adrienharnay
Copy link
Author

Hi,

Thanks for the answer. Indeed, I worked around it by doing:

if (typeof window !== 'undefined') {
  amplitude = require('amplitude-js/amplitude');
}

@blazzy
Copy link
Contributor

blazzy commented Nov 13, 2018

FYI we're tracking a task to get the SDK working in node here: #164

@Vadorequest
Copy link

Alright, I understand that @adrienharnay solution is basically to only require the amplitude-js when running on the browser.

But, it doesn't provide any way of making it work on the server. The SDK is not compatible with node at all? That's a serious limitation for many things, like backend-powered chatbots, etc.

I'm using Next.js and here is what I did:

pages/_app.tsx

import { Amplitude, AmplitudeProvider } from '@amplitude/react-amplitude';
import { ApolloProvider } from '@apollo/react-hooks';
import { isBrowser } from '@unly/utils';

//...

render() {
    const { Component, pageProps, apollo }: any = this.props;

    // Workaround for https://github.com/zeit/next.js/issues/8592
    const { err }: any = this.props;
    const modifiedPageProps = { ...pageProps, err };
    let amplitude;

    if (isBrowser()) {
      amplitude = require('amplitude-js');
    }

    if (modifiedPageProps.isSSRReadyToRender) {
      return (
        <AmplitudeProvider
          amplitudeInstance={amplitude ? amplitude.getInstance() : null} // Amplitude is disabled on the server side
          apiKey={process.env.AMPLITUDE_API_KEY}
        >
          <Amplitude
            eventProperties={{
              scope: ['tfp'],
            }}
          >
            <ApolloProvider client={apollo}>
              <Layout {...modifiedPageProps}>
                <Component {...modifiedPageProps} />
              </Layout>
            </ApolloProvider>
          </Amplitude>
        </AmplitudeProvider>
      );
    } else {
      return null;
    }
  }

So, it works like this (I mean, it doesn't crash when loading the app anymore), I just wonder if that's fine to load things this way, with an amplitudeInstance=null on the server. Is it recommended? I don't see any issue but... you tell me 😄

@Vadorequest
Copy link

For anyone interested by a real use case with Amplitude and Next.js 9 (universal app), check out https://github.com/UnlyEd/next-right-now

Interesting parts are:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants