react-plotly.js icon indicating copy to clipboard operation
react-plotly.js copied to clipboard

JavaScript heap out of memory error with the quickstart Plot example.

Open squeakycheese75 opened this issue 5 years ago • 27 comments

I get the following error if i add a component with the quickstart <Plot/> and run npm start. I have the latest version of both react-plotly.js (2.3.0) and plotly.js (1.47.1)

`Compiling...

<--- Last few GCs --->

[17798:0x2708820] 469928 ms: Mark-sweep 1302.4 (1429.6) -> 1302.3 (1429.6) MB, 2350.9 / 0.0 ms allocation failure GC in old space requested [17798:0x2708820] 472353 ms: Mark-sweep 1302.3 (1429.6) -> 1302.3 (1422.6) MB, 2425.0 / 0.0 ms last resort GC in old space requested [17798:0x2708820] 474681 ms: Mark-sweep 1302.3 (1422.6) -> 1302.3 (1421.1) MB, 2327.7 / 0.0 ms last resort GC in old space requested

<--- JS stacktrace --->

==== JS stack trace =========================================

0: ExitFrame [pc: 0x32090c30427d]

Security context: 0x38b7ade206a9 <JSObject> 1: _append [/home/squeakycheese/Development/git/stockkly/node_modules/@babel/generator/lib/buffer.js:~112] [pc=0x32090ce90eef](this=0x56dca2fd981 <Buffer map = 0x1b38ed9eaad1>,str=0x3d2c8a736e69 <String[1]: >,line=48172,column=22,identifierName=0x3d2c8a702201 ,filename=0x3d2c8a702201 ,force=0x3d2c8a7022e1 ) 2: word [/home/sque...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 1: node::Abort() [node] 2: 0x876afc [node] 3: v8::Utils::ReportOOMFailure(char const*, bool) [node] 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [node] 5: 0xdd42b1 [node] 6: v8::internal::Factory::NewUninitializedFixedArray(int, v8::internal::PretenureFlag) [node] 7: 0xdaf00f [node] 8: v8::internal::Runtime_GrowArrayElements(int, v8::internal::Object**, v8::internal::Isolate*) [node] 9: 0x32090c30427d`

squeakycheese75 avatar Apr 11 '19 10:04 squeakycheese75

See https://github.com/plotly/plotly.js/issues/3604

etpinard avatar Apr 11 '19 14:04 etpinard

Been experimenting with similar results. I had a functional app (testing the waters with React by rewriting something from Angular) that I built by going through a few tutorials.

I switched to a fresh create-react-app and followed instructions for adding react-plotly.js & plotly-js and started getting the errors reported above.

After troubleshooting, I tried downgrading the plotly.js version and it's all working now.

I was using current (react-plotly.js: ^2.3.0, plotly.js: ^1.47.3) with 100% failure downgraded to plotly.js: 1.45.3 and I'm back in business.

Wondering if there was some threshold crossed where the packages were too big from 1.45->1.47

benhastings avatar Apr 18 '19 20:04 benhastings

I faced a similar error with react-plotly.js (2.3.0) and plotly.js (1.47.3), but I could make it work by using yarn in place of npm(though still took more than 1 min for "yarn start"..). Hope it helps :)

magamongo avatar Apr 23 '19 12:04 magamongo

Got it to work by

<script crossorigin src="https://cdn.plot.ly/plotly-latest.min.js"></script>
import createPlotlyComponent from 'react-plotly.js/factory';
const Plotly = window.Plotly;
const Plot = createPlotlyComponent(Plotly);

dhamaniasad avatar Jun 10 '19 12:06 dhamaniasad

We ran into the same issue in our test application. Switched to NodeJS 12.4.0 and webpack built without an out of memory error (so far). But it fails on node 11 and 10.

krimple avatar Jun 12 '19 18:06 krimple

I got it working using exactly the same method as dhamaniasad. So only loading in from the basic-dist.

import React from "react";
// import Plot from "react-plotly.js";
import Plotly from "plotly.js-basic-dist";

import createPlotlyComponent from "react-plotly.js/factory";
const Plot = createPlotlyComponent(Plotly);

I also installed the basic package via npm https://www.npmjs.com/package/plotly.js-basic-dist

squeakycheese75 avatar Jun 12 '19 18:06 squeakycheese75

Also, just launched via

node --max_old_space_size=4096 /path/to/nodejs/bin/yarn start

This was on 10.15.2. Node 12 increased the heap sizes automatically, which is why it worked.

krimple avatar Jun 12 '19 18:06 krimple

I initially played around with changing the "max_old_space" but couldn't get it working. Also, it seemed a bit off having to increase the heap size just to load the simplest of charts.

squeakycheese75 avatar Jun 12 '19 18:06 squeakycheese75

did you use max_old_space_size rather than max_old_space? Just curious. I agree, it needs to be fixed so that this isn't a problem. Am worried that suddenly we'll run into this limit again when our code touches more of the library.

krimple avatar Jun 12 '19 18:06 krimple

Apologies but I can't remember. It was a while ago when I found the above fix and gave up on adjusting the heap size.

squeakycheese75 avatar Jun 12 '19 18:06 squeakycheese75

Updating to the most recent version of Node 12+ helped allocated the heap size automatically as stated by @krimple earlier.

I then went with using the react-plotly.js-dist the same way @squeakycheese75 displayed his imports and now everything is working!

import React from 'react';
import Plotly from 'plotly.js-dist';
import createPlotlyComponent from 'react-plotly.js/factory';
const Plot = createPlotlyComponent(Plotly);

francesco-hayes avatar Jun 18 '19 15:06 francesco-hayes

Also, just launched via

node --max_old_space_size=4096 /path/to/nodejs/bin/yarn start

This was on 10.15.2. Node 12 increased the heap sizes automatically, which is why it worked.

So, another words saying: just update to NodeJS 12 and forget about this problem

MinskLeo avatar Jul 05 '19 13:07 MinskLeo

Does this mean that the current version of plot.ly is not compatible with React apps built on CRA running on LTS?

brianbancroft avatar Jul 24 '19 18:07 brianbancroft

you may also hack a bit the build system with

  1. npm run eject -- you will get the building sources of reaact
  2. goto config/webpack.config.js and add
    externals: [
      function(context, request, callback) {
        if(irequest === 'plotly.js/dist/plotly') {
          callback(null, 'window.Plotly');
        } else {
          callback();
        }
      }
    ],
  1. add to config/webpack.config.js also following
plugins: [
// ....
        new CopyPlugin([
          { 
            from: path.join(paths.appNodeModules, 'plotly.js', 'dist', 'plotly.min.js'),
            to: 'static/js'
          }
        ])
//...
]
  1. in public/index.html add following <script type="text/javascript" src="%PUBLIC_URL%/static/js/plotly.min.js"></script>

something like this, I hope you got the idea

jonyrock avatar Aug 30 '19 16:08 jonyrock

Running into the exact same problem, it didn't happen using react-scripts 1.1.4, but it started happening when I updated to 2.1.8. Worked around it with @squeakycheese75's solution, thank you!

rafaponieman avatar Oct 18 '19 16:10 rafaponieman

Finally, I updated to node 12.12, and it worked without @squeakycheese75's fix.

rafaponieman avatar Oct 18 '19 18:10 rafaponieman

Updating Node to version 12 LTS fixed the error.

ashiqsultan avatar Nov 02 '19 05:11 ashiqsultan

@squeakycheese75 thank you so much, the solution that use the plotly.js-basic-dist worked to me also!

felipesousa avatar Feb 03 '20 18:02 felipesousa

using @squeakycheese75 method works but I cannot get a scatter3d chart to work this way. Are there some other parameters to createPlotlyComponent?

Nevermind, the basic dist does not have scatter 3d. I'm still stuck with this issue on Node version: 12.15.0, react-plotly.js: 2.4.0

brswan avatar Feb 11 '20 20:02 brswan

This same error happened to me using the basic example on npm & github. using the @squeakycheese75 (https://github.com/plotly/react-plotly.js/issues/135#issuecomment-501398125) method I was able to render a basic plot.

jstafford74 avatar Feb 18 '20 10:02 jstafford74

Changing the lines in package.json worked for me as a hacky workaround:

"start": "react-scripts --max_old_space_size=4096 start", "build": "react-scripts --max_old_space_size=4096 build",

devdev999 avatar Feb 26 '20 14:02 devdev999

Is there a ELI5 of why this is happening?

qzhang1 avatar Jul 04 '20 14:07 qzhang1

@MinskLeo Node upgrade cannot solve the problem completely.

For example, I have the same problem with: node v12.18.2 react: 16.13.1

Solution provided by @devdev999 can solving the problem. (--max_old_space_size=4096)

ievgennaida avatar Aug 04 '20 21:08 ievgennaida

@jonyrock's solution is by far the best for me. I'm getting heap issues trying to run npm build on a Raspberry Pi 4 1Gb. As I can't increase my available memory (and switching to nodejs v12+ doesn't help), I've used his solution to make plotly an external script. This gives me fast compile times and no issues. Thanks!

toastedcrumpets avatar Nov 07 '20 16:11 toastedcrumpets

Almost 2 years later and this issue still persists. dhamaniasad's solution works but doesn't feel sensible long term.

EliasHem avatar Mar 17 '21 08:03 EliasHem

Got it working similar to https://github.com/plotly/react-plotly.js/issues/135#issuecomment-501398125 (edit: by minimizing plotly, not using a script w/ cross-origin) , but using the files in plotly.js/lib directly to make a custom bundle. For example, if one wants to make a React component of just a scatter plot, make a file titled Plotly_scatter.js with the following lines:

import Plotly from 'plotly.js/lib/core'
import PlotlyScatter from 'plotly.js/lib/scatter'

Plotly.register(PlotlyScatter)

export default Plotly

Then, in a component file called Scatter.js, do:

import Plotly from 'path/to/Plotly_scatter'
import createPlotlyComponent from 'react-plotly.js/factory'
const Plot = createPlotlyComponent(Plotly)

And use it exactly as shown in the demo.

You can DIY your own bundle by doing the following (taken from plotly.js modules documentation):

// Load in the trace types for pie, and choropleth
import Plotly from 'plotly.js/lib/core'
// Register traces to Plotly core
Plotly.register([
    require('plotly.js/lib/pie'),
    require('plotly.js/lib/choropleth')
]);
// Export custom bundle
export default Plotly

If you're using Typescript like myself, I ran into some trouble with the plotly.js definitions in DefinitelyTyped. In the repo, scatter.d.ts is defined, but importing scatter directly from lib throws an error about missing type definitions. Looking at it, I found that the type definitions are really sparse and only partially cover Plotly. To get around this, I opted for the hacky way and added "plotly.js/lib/core" (otherwise register() isn't recognized) and a line for each "plotly.js/lib/<plot-type>" to the decs.d.ts file (I'm new to all of this, so there's probably a more efficient module declaration). This is bad practice, but I'm not up to making the type defs myself.

All that said and done, using the specific parts of Plotly as needed does speed up the npm build by a lot (~15-25 seconds for ~~one plot~~ plots (I have since added more and it hasn't affected the build time noticeably) down from 2-3 minutes), and I think this is a good way to apply React's composition principle to Plotly.

Hope it helps someone.

Aweptimum avatar Mar 25 '21 16:03 Aweptimum

@squeakycheese75, We had similar issues here and the solution was to import the Plot component using lazy load.

First approach: lazy load within the desired page.

Before

/** ChartPage.js **/

import React from 'react'
import Plot from 'react-plotly.js'

const ChartPage = () => {
   return(
      <div>
        <Plot data={data} layout={layout} config={config} />   
      </div>
   )
   
 export default ChartPage

After

/** ChartPage.js **/

import React, {useMemo} from 'react'

const ChartPage = () => {

  const Plot = useMemo(() => {
    return React.lazy(() => import('react-plotly.js'));
  }, []);

   return(
      <div>
        <Plot data={data} layout={layout} config={config} />   
      </div>
   )
   
 export default ChartPage
  

Second approach: lazy load the entire page (Recommended)

Before

/** Router.js **/

import React from 'react'
import ChartPage from '../pages/ChartPage'

...
<Route path="/chart" component={ChartPage} />
...

After

/** Router.js **/

import React from 'react'

const ChartPage = React.lazy(() => import('../pages/ChartPage'))

...
<Route path="/chart" component={ChartPage} />
...

Both solutions solved the issue here, but the second one avoid glitches after the page has already been rendered.

amaralc avatar Apr 26 '21 17:04 amaralc