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

remove extra js eval call #1544

Merged
merged 3 commits into from
Jul 17, 2023

Conversation

wyattades
Copy link
Contributor

@wyattades wyattades commented Jun 12, 2023

Summary

The current implementation calls ExecJS::Runtime#eval twice during every react server-side render, but we can refactor it to only call eval once.

This causes a 2x speedup (e.g. 800ms -> 400ms) with the Node.js runtime, and other runtimes with slow IO.

Pull Request checklist

  • Add/update test to cover these changes
  • Update documentation
  • Update CHANGELOG file

Other Information


This change is Reviewable

railsContext: railsContext
});
} finally {
console.history = [];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alternatively, we could move this into serverRenderReactComponent. I'll let you all decide

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good solution.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, @Judahmeek @ahangarha @KhaledEmaraDev This line would be a great place to add a configurable cleanup code for SSR. For example, in the past, I saw weird side effects from MobX on SSR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wyattades I see your point that we could move console.history = []; to here: https://github.com/shakacode/react_on_rails/blob/master/node_package/src/serverRenderReactComponent.ts#L12

One can argue that it makes sense to keep the generated JS as small as possible, so I like that solution.

@Judahmeek @alexeyr-ci what do you guys think?

I vote we:

  1. rename the current function serverRenderReactComponent to something like serverRenderReactComponentInternal and not export it.
  2. Create serverRenderReactComponent in the same file with the try/finally block.

Copy link
Collaborator

@alexeyr-ci alexeyr-ci Jul 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If nobody calls serverRenderReactComponentInternal other than serverRenderReactComponent, why bother creating it (instead of just adding try/finally there directly)? If someone does, sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Easier to read. Function is already too long.

@justin808
Copy link
Member

Awesome work @wyattades. Can you document how you profiled this? Maybe you could add such information to CONTRIBUTING.md?

Copy link
Member

@justin808 justin808 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work.

To merge, I'd like to see:

  1. Tests for the changes if easy to do.
  2. We need to deprecate or prevent eval_js from being called directly, as it won't clear the console.history any more.
  3. We need a changelog.md entry.

railsContext: railsContext
});
} finally {
console.history = [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good solution.

@wyattades
Copy link
Contributor Author

Tests for the changes if easy to do.
We need a changelog.md entry.

Can do, probably by next week.

Can you document how you profiled this? Maybe you could add such information to CONTRIBUTING.md?

I don't have anything reproducible at the moment, since I tested it against a private project. But this would be as simple as running a benchmark on request durations on the dummy project. Maybe it'd be good to make a bin/benchmark script that tests a few different execjs runtimes and React SSR scenarios?

We need to deprecate or prevent eval_js

I don't see any documentation that it's public, do we need deprecation?

@justin808
Copy link
Member

@wyattades

I don't see any documentation that it's public, do we need deprecation?
Correct! we don't!

@alexeyr-ci
Copy link
Collaborator

I checked if we have similar problems elsewhere and I don't think so (at least with eval calls). There is

def wait_for_ajax
Timeout.timeout(Capybara.default_max_wait_time) do
loop until finished_all_ajax_requests?
end
end
def finished_all_ajax_requests?
page.evaluate_script("jQuery.active").zero?
end

but it's in tests.

@Judahmeek
Copy link
Contributor

@wyattades can you also rebase on master?

CI won't pass until you do since we had some of the jobs set to trigger on push only, which meant that they didn't trigger for PRs from forks.

This oversight was corrected by #1553

.prettierrc Outdated Show resolved Hide resolved
@wyattades
Copy link
Contributor Author

Can you document how you profiled this? Maybe you could add such information to CONTRIBUTING.md?

Made a separate PR for this, since I ran into some issues with the dummy app #1555

Copy link
Member

@justin808 justin808 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to put formatting in separate PR.

@wyattades wyattades force-pushed the wa/remove-extra-js-eval-call branch from b0aebd2 to 4e248cc Compare July 16, 2023 02:20
@wyattades wyattades requested a review from justin808 July 17, 2023 05:32
@justin808 justin808 merged commit 005e26e into shakacode:master Jul 17, 2023
@justin808
Copy link
Member

Nice and small update!

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

Successfully merging this pull request may close these issues.

4 participants