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

React on Rails and async loading of application.js #290

Closed
SqueezedLight opened this issue Feb 23, 2016 · 14 comments
Closed

React on Rails and async loading of application.js #290

SqueezedLight opened this issue Feb 23, 2016 · 14 comments

Comments

@SqueezedLight
Copy link
Contributor

Hi guys,
i'm wondering if there is any possibility to use react on rails with async loading like:

<%= javascript_include_tag 'application', async: Rails.env.production? %>

In this case, the componentDidMount does not get fired. The issue is well known, described and fixed here: reactjs/react-rails#218

What i'm searching for is a hook, like ReactRailsUJS.mountComponents(). Right now i'm trying to write something like mountComponents() but i did not have success until now. That's why i'm wondering if i'm missing something?

Thanks a lot in advance.

@justin808
Copy link
Member

@SqueezedLight Any research you can do this topic would be greatly appreciated!

I think this already does what you need:

https://github.com/shakacode/react_on_rails/blob/master/node_package%2Fsrc%2FclientStartup.js#L93

function reactOnRailsPageLoaded() {
  debugTurbolinks('reactOnRailsPageLoaded');

  forEachStore(initializeStore);
  forEachComponent(render);
}

We simply need to export the function and expose it here in the main ReactOnRails js class.

https://github.com/shakacode/react_on_rails/blob/master/node_package%2Fsrc%2FReactOnRails.js#L59

Can you try that out and send a PR including:

  1. Docs
  2. Tests: put this into spec/dummy app to demonstrate this.

Thanks!

@SqueezedLight
Copy link
Contributor Author

@justin808 Thanks, i didn't see that in the first place. I'm on it...

@justin808
Copy link
Member

@SqueezedLight Any update? Should we leave this issue open?

@SqueezedLight
Copy link
Contributor Author

@justin808 Sorry, i had to manage some really stressful days...

Yes, there is some progress: Exposing reactOnRailsPageLoaded() to ReactOnRails worked like a charm. But i'm using turbolinks 5.0 and i'm calling some code within document.addEventListener("turbolinks:load", function() {}); This peace of code stopped working, because it seems turbolinks does not fire turbolinks:load on initial page load with async script loading. One solution is to use defer instead of async. More information can be found on the issue i opened about this topic: turbolinks/turbolinks#28

So i managed to get everything working with async script loading. I hope i can make the PR on the weekend.

@justin808 justin808 removed the easy label Mar 31, 2016
@justin808
Copy link
Member

Merged with version 6.0.0-rc.1

@xiaopow
Copy link

xiaopow commented Sep 13, 2016

If I want to load the js async, do I just add
<%= javascript_include_tag 'application', async: true %>
?

Or is there more settings I need to configure?

@justin808
Copy link
Member

@xiaopow I don't know off the top of my head. Please research this and report back to us, and that will help the community.

@justin808
Copy link
Member

@xiaopow, @nateberkopec has some done some amazing research into this area. Nate, can you give us a few links to your materials?

@dpuscher
Copy link

dpuscher commented May 23, 2017

I ran into the same problem, where my javascript wasn't executed reliably when loading my generated application.js asynchronously via javascript_pack_tag "application", async: true.

A quick workaround was this snippet:

if (typeof document !== "undefined") {
  if (document.readyState !== "loading") {
    ReactOnRails.reactOnRailsPageLoaded();
  } else {
    document.addEventListener("DOMContentLoaded", () =>
      ReactOnRails.reactOnRailsPageLoaded(),
    );
  }
}

I am not sure if I need the event listener since this might be what react_on_rails is doing to initialize the components and it will fail if the DOM had finished loading when the JS is loaded.

Maybe someone knows a better way, or did I miss something from the docs? Nowadays it should be the preferred way to load the JS async (especially when prerendering components).

JonathanWThom added a commit to JonathanWThom/philosophy-blog that referenced this issue Mar 31, 2018
Dropped about 200ms from page load time on `posts#index` locally. Some
folks [have reported issues](shakacode/react_on_rails#290)
with this, but it seems to be working fine for me.

I calculated page load time with this:

```
var loadTime = window.performance.timing.domContentLoadedEventEnd - window.performance.timing.navigationStart;
```
justin808 added a commit that referenced this issue Jun 24, 2018
Fixes #290, transparently handling <script async> tag. If the document was already loaded,
the DOMContentLoaded event handler no longer fires, so we just execute it directly, the
same way as jQuery does in $.ready().

Co-authored-by: Alexey Makhotkin
justin808 added a commit that referenced this issue Jun 25, 2018
* Handle <script async> transparently #1099

Fixes #290, transparently handling <script async> tag. If the document was already loaded,
the DOMContentLoaded event handler no longer fires, so we just execute it directly, the
same way as jQuery does in $.ready().

* Added async tag to spec/dummy


Co-authored-by: Alexey Makhotkin
@julianguyen
Copy link

Is there an official way of doing this in React on Rails now, instead of the solution @dpuscher mentioned above?

@justin808
Copy link
Member

@julianguyen I'm sure this is somewhere in the docs.

Here's an example:
https://github.com/shakacode/react_on_rails/blob/master/spec/dummy/app/views/layouts/application.html.erb#L17

you need to use defer:

  <!--  NOTE: Must use defer and not async to keep async scripts loading in correct order  -->
  <%= javascript_pack_tag('vendor-bundle', 'data-turbolinks-track': true, defer: true) %>
  <%= javascript_pack_tag('app-bundle', 'data-turbolinks-track': true, defer: true) %>

@julianguyen
Copy link

@justin808 Why does 'data-turbolinks-track': true need to be set with defer?

@rakelley
Copy link
Contributor

@julianguyen If you don't use turbolinks, you get problems. #1150

@justin808
Copy link
Member

@julianguyen if you are not using turbolinks, remove that part.

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

Successfully merging a pull request may close this issue.

6 participants