Search code examples
javascriptnode.jsreactjsgsapserver-side-rendering

How to disable or prevent ReactJS from looking for a document when it server side renders?


I am trying to use GSAP within my ReactJS app for animation on the client side. If I install the gsap module via npm and then try to use gsap within my modules, I get the following error:

node_modules/gsap/src/uncompressed/TweenMax.js:2535
            _doc = document,
                   ^

ReferenceError: document is not defined
    at Function.<anonymous> (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:2535:11)
    at [object Object].check (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:5794:61)
    at new Definition (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:5811:10)
    at window._gsDefine (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:5816:12)
    at Array.<anonymous> (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:2489:11)
    at /Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:7570:9
    at Object.<anonymous> (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:7581:3)
    at Module._compile (module.js:435:26)
    at Module._extensions..js (module.js:442:10)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/babel-register/lib/node.js:138:7)

Is there a way in ReactJS to code: If it renders on the server, there's no document so don't load gsap, but once the compiled bundle.js (my client side react js that takes over the client) is downloaded, use gsap because the document exists?

The work around I'm currently using is to embed gsap in the index.ejs:

<!DOCTYPE html>
<html>
  <head>
    <title>Solid Website</title>
  </head>

  <body>
    <section id="react-app" class="container-fluid">
      <%- markup %>
    </section>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TimelineMax.min.js"></script>
    <script src="build.js"></script>
  </body>
</html>

Update: the webpack.config.js

var path = require('path');

module.exports = {
  entry: path.join(process.cwd(), 'client-render.js'),
  output: {
    path: './public/',
    filename: 'build.js'
  },
  module: {
    loaders: [
      {
        loader: 'babel'
      }
    ]
  }
}

Solution

  • In my webpack.config.js:

    module.exports = {
      entry: path.join(process.cwd(), 'client/client-render.js'),
      output: {
        path: './public/',
        filename: 'build.js'
      },
      module: {
        loaders: [
          {
            test: /.js$/,
            loader: 'babel'
          }
        ]
      },
      /* this is new */
      plugins: [
        new webpack.DefinePlugin({
          'process.env': {
            NODE_ENV: JSON.stringify('production'),
            APP_ENV: JSON.stringify('browser')
          }
        })
      ]
    }
    

    Then in my modules:

    if (process.env.APP_ENV === 'browser') {
      load_the_module_for_browser;
    }