react-rails icon indicating copy to clipboard operation
react-rails copied to clipboard

SSR ExecJS::ProgramError when using client side code splitting

Open bcharna opened this issue 7 years ago • 6 comments

Steps to reproduce

I have a component that has a componentDidMount like so:

  public async componentDidMount() {
    const [Foo, Bar] = await Promise.all([
      import(/* webpackChunkName: "stuff" */ 'foo'),
      import(/* webpackChunkName: "stuff" */ 'bar'),
     ]);
    this.setState({
      Foo: Foo.default,
      Bar: Bar.default,
    });
  }

Expected behavior

Since the import occurs inside componentDidMount, it's expected that that code does not cause issues when using SSR with ExecJS. In this code, the intention is for code splitting to occur for the client side only.

Actual behavior

A ExecJS::ProgramError is raised, stating 'ReferenceError: window is not defined'. I have eliminated it down to this code which happens to be the very beginning of the server_rendering.js output:

/******/ (function(modules) { // webpackBootstrap
/******/ 	// install a JSONP callback for chunk loading
/******/ 	var parentJsonpFunction = window["webpackJsonp"];
...

If I change componentDidMount to be blank (or really just remove the import calls in it), webpack does not add the above snippet and no SSR error occurs. Is there a mechanism within this gem to allow for client side code splitting like this and still allow for the component to be rendered server-side?

System configuration

Sprockets or Webpacker version: Webpacker 3.5.3 React-Rails version: 2.4.7 Rect_UJS version: 2.4.4 Rails version: 5.2.0 Ruby version: 2.5.1p57

bcharna avatar Aug 08 '18 05:08 bcharna

👀

ttanimichi avatar Aug 08 '18 06:08 ttanimichi

@bcharna Although I have this issue as well on a project I'm working on, I don't think this is related to react-rails at all, but indeed webpack, so, I'm thinking reporting it to the https://github.com/rails/webpacker people will be more useful.

jdfm avatar Jan 15 '19 21:01 jdfm

Same problem

dachinat avatar Feb 11 '19 20:02 dachinat

This can be fixed by setting output.globalObject: 'this' in your webpack.config.js. You almost certainly have not set a target value in your module.exports or have it set to 'web' (the default if you don't set it). This causes Webpack to assume window is the appropriate global.

module.exports = {
...
    output:{ 
        ...
        globalObject: 'this',
        ...
    }
...
}

Editing to add documentation link: https://webpack.js.org/configuration/output/#outputglobalobject

To make UMD build available on both browsers and Node.js, set output.globalObject option to 'this'.

erikt9 avatar Sep 29 '19 03:09 erikt9

@erikt9 That's a good find. Can someone confirm the above post fixes it for them, then could you consider adding this to the Readme?

BookOfGreg avatar Sep 30 '19 07:09 BookOfGreg

I'm looking into the above fix, will report back!

nopelluhh avatar Oct 02 '19 23:10 nopelluhh

It makes sense to close this issue, as we discussed a fix here.

alkesh26 avatar Nov 03 '22 08:11 alkesh26