3

I'm trying to add a JavaScript library that is only included in the production build files generated by create-react-app.

What's the best way to do this?

Specifically, I'm trying to include the Rollbar.js client-side error monitoring library. I don't want it triggering every time I get an error in development/testing environments, so I only want it included in the files that are generated while running npm run build.

MattSidor
  • 2,599
  • 4
  • 21
  • 32
  • Is checking against `process.env.NODE_ENV` sufficient? i.e. a conditional require? This is how you would normally do things like including devtools only for development, etc. – Samo Feb 23 '18 at 19:39
  • Can you paste some of what you've tried? – Samo Feb 23 '18 at 20:48
  • I've tried including their "Quick start browser" ` – MattSidor Feb 23 '18 at 21:02
  • Sorry I wasn't clear, I meant that you should modify the question itself by pasting code snippets of things you've tried. As for the script tag approach, you could use a different index.html file when building for production. Your second claim I'm skeptical of and I'd like to see specifically what you tried so that I can test it and make a suggestion. – Samo Feb 24 '18 at 17:29
  • However I see you've solved your problem so no worries :) – Samo Feb 24 '18 at 17:30
  • Samo - `import` statements must always be declared first in ES2015. See also - https://stackoverflow.com/questions/34203325/why-must-export-import-declarations-be-on-top-level-in-es2015. If you doubt it, use the create-react-app CLI to make an app and try inserting `const Rollbar = require('rollbar');` before the `import` statements of `index.js`. – MattSidor Feb 25 '18 at 06:05
  • I don't doubt that, but your first statement could easily import a local file that then uses a conditional require on rollbar. – Samo Feb 25 '18 at 21:22
  • I tried this and couldn't get it to work. Let me know if you can get it working. – MattSidor Feb 25 '18 at 21:48

2 Answers2

8

The answer provided by tpdietz is a very good one and would probably work well for many libraries.

However, this specific library I'm trying to use (Rollbar) needs to be loaded before any other JavaScript (e.g. React and ReactDOM), or else it can't capture all errors. Since those other libraries are loaded via import statements, I can't use a require statement in front of them at the top of index.js.

The solution I found (thanks to GitHub user rokob with the Rollbar.js project) is to reference the NODE_ENV variable from within the index.html file, as described here: https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#referencing-environment-variables-in-the-html

At the top of my index.html file, in a <script> tag, I can set a variable to %NODE_ENV%. The build process for create-react-app will automatically parse that variable and insert the name of the environment, e.g. "production" or "development", in the final index.html file. Then, I can check to see if that variable is equal to "production" before executing any inline JavaScript.

Example index.html:

<!doctype html>
<html lang="en">
<head>
  <script>
    var environment = "%NODE_ENV%";
    if (environment === "production") {
      // code here will only run when index.html is built in production environment
      // e.g. > $ NODE_ENV="production" npm run build
    }
  </script>

In the specific case of Rollbar.js, I just needed to pass a config parameter with the environment name, so no if statement is necessary:

var _rollbarConfig = {
  ...
  enabled: ('%NODE_ENV%' === 'production')  //returns true if 'production'
  ...
};

Here is the issue on Github where rokob gave me this solution: https://github.com/rollbar/rollbar.js/issues/583

MattSidor
  • 2,599
  • 4
  • 21
  • 32
4

You can use environment variables. For example:

if (process.env.NODE_ENV === 'production') {
  const Rollbar = require('rollbar');
}

You can invoke the build command like with a NODE_ENV var like so:

NODE_ENV="production" npm run build

Its worth noting you cannot conditionally use import syntax.

tpdietz
  • 1,358
  • 9
  • 17
  • I think he wants this only in production. – Samo Feb 23 '18 at 19:48
  • Changed "development" to "production" :) ty – tpdietz Feb 23 '18 at 19:55
  • Thank you; this is very helpful. However, Rollbar specifically must be loaded before any other libraries, e.g. React and ReactDOM. When I try to add `const Rollbar = require('rollbar');` before the other `import` statements in my `index.js` file, I get errors. – MattSidor Feb 23 '18 at 20:09