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

Hydration DOM Fixture #13521

Merged
merged 37 commits into from
Sep 10, 2018
Merged

Hydration DOM Fixture #13521

merged 37 commits into from
Sep 10, 2018

Conversation

nhunzaker
Copy link
Contributor

@nhunzaker nhunzaker commented Aug 30, 2018

It's still a little rough, but @gaearon nudged me to send this over anyway.

This PR adds a hydration fixture to the manual test fixtures. You can play around with it here:

http://react-hydration.surge.sh/hydration

Why we need this fixture

Testing client bugs related to hydrating markup is hard. Additionally, network conditions and browser plugins are difficult to test with JSDOM. Having an interactive tool makes it much easier to demonstrate problems and accidentally uncover new ones.

For example:

Change events do not fire on hydrated inputs

  1. Visit http://react-hydration.surge.sh/hydration
  2. Uncheck the "Hydrate" checkbox
  3. Change the text in the right-hand panel
  4. Click the "Hydrate" button
  5. Observe that no change event occurs

React warns when 1Password adds meta data

  1. Add the 1Password browser addon
  2. Visit http://react-hydration.surge.sh/hydration
  3. Uncheck the "Hydrate" checkbox
  4. Change the text in the right-hand panel
  5. Notice that 1Password adds data attributes to the input
  6. Click the "Hydrate" button
  7. Notice warnings in the console for data attributes that we have no control over. Should we warn in this case?

Things to do

  • Make sure this works back to (maybe) 0.14.0
  • Can't load in 15.6.2 (different path)
  • Verify IE9/10
  • Verify Firefox ESR
  • Verify Chrome 49
  • Verify Safari 7.1

screen shot 2018-08-30 at 3 30 22 pm

import './hydration.css';
import {SAMPLE_CODE} from './data';
import {LiveProvider, LiveEditor, LiveError} from 'react-live';
import * as buble from 'buble';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Buble is the best!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually... spoke too soon (buble is still great) it turns out I needed Babel. Buble uses some __proto__ tricks that break in IE9/10.

To get IE9 support, I ended up pulling in babel/standalone with a few polyfills.

@@ -167,7 +167,7 @@ if (__DEV__) {
attributeNames.forEach(function(name) {
names.push(name);
});
warningWithoutStack(false, 'Extra attributes from the server: %s', names);
warningWithoutStack(false, 'Extra attributes from the server: %s', names.join(', '));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverting this. This fixture caught this bug while I was working on it. I sent out a PR here:
#13385

@nhunzaker
Copy link
Contributor Author

I believe this is ready for review. I've also verified that it works down to React 14.8 on IE9/10, Firefox 52, Safari 7.1, and Chrome 49 (but also the latest Firefox and Chrome)

@pull-bot
Copy link

pull-bot commented Sep 6, 2018

Details of bundled changes.

Comparing: 8a8d973...81dcf6c

schedule

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
schedule.development.js n/a n/a 0 B 19.17 KB 0 B 5.74 KB UMD_DEV
schedule.production.min.js n/a n/a 0 B 3.16 KB 0 B 1.53 KB UMD_PROD

Generated by 🚫 dangerJS

@nhunzaker
Copy link
Contributor Author

Well shoot... for some reason CodeMirror's layout messes up on the production build. I promise this looks okay:

screen shot 2018-09-06 at 3 37 43 pm

I'll figure it out.

@nhunzaker
Copy link
Contributor Author

Easiest thing is just to set a fixed height.

Copy link
Contributor

@philipp-spiess philipp-spiess left a comment

Choose a reason for hiding this comment

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

Awesome! I think it makes sense to have such a fixture. I also believe it's fine to add babel if we don't have any other choice.

Everything worked fine for me locally when using Chrome. 👍

Design Review

We should make the container bigger at least for the hydration fixture. Ideally we can print 80 characters in the editor without needing to scroll horizontally. Is this doable?

In addition to that, we should also use a bigger width for the error message when babel can't compile. There should also be <br>s between the individual lines if that isn't too much work.

I'm also not a super huge fan of the codemirror theme but since you've pushed the PR you can pick whatever you want 🙂

var renders = 0;
var failed = false;

function query(key) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I was a bit confused about what we're querying here. Maybe getQueryParam() makes it less confusing? 🙂

Author: Jan T. Sott

Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror)
Inspired by the art of Rubens LP (http://www.rubenslp.com.br)
Copy link
Contributor

Choose a reason for hiding this comment

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

License looks 👍 But we need to include the copyright notice I believe (see here).

Seems like the GitHub files already added this 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

}

function injectFixture(src) {
window.Fixture = undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we put the Fixture into the closure of this file instead of the global namespace? I was confused where this was set when in fact it is very easy and all in the same file 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup. See d5a4acd

checked={hydrate}
onChange={this.setCheckbox}
/>
Hydrate
Copy link
Contributor

Choose a reason for hiding this comment

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

I was confused about this checkbox. Maybe "Hydrate on reload" or "Auto Hydrate" makes it clearer?

Especially when this checkbox is unchecked you see a button with the same name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great idea! See 437c45b

This prevents a bug where Chrome reports `Array(n)` where `n` is the
size of the array.
This commit adds a homepage to the DOM fixtures that includes browser
testing information and asynchronously loads fixtures.

This should make it easier to find DOM testing information and keep
the payload size in check as we add more components to the fixtures.
This commit adds a first pass at a fixture that makes it easier to
debug the process of hydrating static markup. This is not complete:

1. It needs to be verified across multiple browsers
2. It needs to render with the current version of react

Still, it at least demonstrates the idea. A fixture like this will
also be helpful for debugging change events for hydrated inputs, which
presently do not fire if the user changes an input's text before
hydration.
This commit makes a few tweaks to support older browsers and updates
the code transition process to use window.postMessage. This avoids
loading React on every single change.
For clarity, and so that the Fixture component does not need to be
assigned to the window, this commit changes the way code is executed
such that it evaluates using a Function constructor.
This commit extends the hydration fixture such that it takes up the
full screen view. To accomplish this, the container that wraps all
fixtures has been moved to the FixtureSet component, utilized by all
other fixtures.
This commit fixes an issue where CodeMirror wouldn't layout correctly
in production builds because the editor executes before the stylesheet
loaded. CodeMirror needs layout information, and was rendering
off-screen without correct CSS layout measurements.
@nhunzaker
Copy link
Contributor Author

Okay! I got a little carried away, but I think I've made a lot of improvements:

http://react-hydration.surge.sh/hydration

image

I still need to do some browser testing, but over all I think I was able to get the design changes while simplifying the layout. I'm pretty happy.

@nhunzaker
Copy link
Contributor Author

nhunzaker commented Sep 9, 2018

The error message is now collapsable too:

screenshot 2018-09-09 at 1 15 26 pm

image

}

function injectFixture(src) {
Fixture = new Function(src + '\nreturn Fixture;')();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@philipp-spiess great call here. I was evaluating this in the context of the window, but I'm pretty sure we can keep it local just using a Function constructor.

@philipp-spiess
Copy link
Contributor

Oh wow, this looks really cool now 😎

I tested IE9 and Safari 7.1. In both browsers, the error message does not appear to work 😕 The error is different though.

screen shot 2018-09-09 at 23 54 34

screen shot 2018-09-09 at 23 57 41

I have no idea if it worked before your changes. Latest Chrome, Firefox, and Safari work great!

This commit fixes an error in Safari 7.1 where Chalk highlighted Babel
errors caused a crash when setPrototypeOf was called within the
library.

This is also an issue on IE9, however this fix does not resolve issues
in that browser.
- Reverts highlighting change. Polyfilling Safari 7.1 is sufficient
- Do not render a details tag in IE9
@nhunzaker
Copy link
Contributor Author

nhunzaker commented Sep 10, 2018

@philipp-spiess Thanks! It looks like this happens when Babel highlights errors. I was able to resolve the issue in Safari 7 by adding the setPrototypeOf polyfill. This will not work for IE9.

I'm not really sure what to do in IE9 short of fixing these lines in Chalk:
https://github.com/chalk/chalk/blob/a6ad9454525c0af602931049155cc51eccc72bb4/index.js#L39-L40

I think this is probably fine for now. It only affects IE9.

@nhunzaker
Copy link
Contributor Author

Thanks for the fantastic review, @philipp-spiess!

@nhunzaker nhunzaker merged commit f6fb03e into facebook:master Sep 10, 2018
Simek pushed a commit to Simek/react that referenced this pull request Oct 25, 2018
* Add home component. Async load fixtures.

This commit adds a homepage to the DOM fixtures that includes browser
testing information and asynchronously loads fixtures.

This should make it easier to find DOM testing information and keep
the payload size in check as we add more components to the fixtures.

* Adds experimental hydration fixture

This commit adds a first pass at a fixture that makes it easier to
debug the process of hydrating static markup. This is not complete:

1. It needs to be verified across multiple browsers
2. It needs to render with the current version of react

Still, it at least demonstrates the idea. A fixture like this will
also be helpful for debugging change events for hydrated inputs, which
presently do not fire if the user changes an input's text before
hydration.

* Tweak select width

* Manually join extra attributes in warning

This prevents a bug where Chrome reports `Array(n)` where `n` is the
size of the array.

* Transform with buble

* Eliminate dependencies

* Pull in react-live for better editing

* Handle encoding errors, pass react version

* Load the correct version of React

* Tweaks

* Revert style change

* Revert warning update

* Properly handle script errors. Fix dom-server CDN loading

* Fix 15.x releases

* Use postMessage to reduce latency, support older browsers

This commit makes a few tweaks to support older browsers and updates
the code transition process to use window.postMessage. This avoids
loading React on every single change.

* Fix fixture renamespacing bug

* Gracefully fallback to textarea in React 14

* Replace buble with babel, react-live with codemirror

* Simplify layout to resolve production code-mirror issues

* Tweak height rules for code-mirror

* Update theme to paraiso

* Format Code.js

* Adjust viewport to fix CodeMirror resize issue in production build

* Eliminate react-code-mirror

* Improve error state. Make full stack collapsable

* Add link to license in codemirror stylesheet

* Make code example more concise

* Replace "Hydrate" with "Auto-hydrate" for clarity

* Remove border below hydration header

* Rename query function in render.js

* Use Function(code) to evaluate hydration fixture

For clarity, and so that the Fixture component does not need to be
assigned to the window, this commit changes the way code is executed
such that it evaluates using a Function constructor.

* Extend hydration fixture to fill width. Design adjustments

This commit extends the hydration fixture such that it takes up the
full screen view. To accomplish this, the container that wraps all
fixtures has been moved to the FixtureSet component, utilized by all
other fixtures.

* Improve error scroll state

* Lazy load CodeMirror together before executing

This commit fixes an issue where CodeMirror wouldn't layout correctly
in production builds because the editor executes before the stylesheet
loaded. CodeMirror needs layout information, and was rendering
off-screen without correct CSS layout measurements.

* Fix indentation on error message

* Do not highlight errors from Babel. Add setPrototypeOf polyfill

This commit fixes an error in Safari 7.1 where Chalk highlighted Babel
errors caused a crash when setPrototypeOf was called within the
library.

This is also an issue on IE9, however this fix does not resolve issues
in that browser.

* Increase resilience to bad errors in Hydration fixture

- Reverts highlighting change. Polyfilling Safari 7.1 is sufficient
- Do not render a details tag in IE9
jetoneza pushed a commit to jetoneza/react that referenced this pull request Jan 23, 2019
* Add home component. Async load fixtures.

This commit adds a homepage to the DOM fixtures that includes browser
testing information and asynchronously loads fixtures.

This should make it easier to find DOM testing information and keep
the payload size in check as we add more components to the fixtures.

* Adds experimental hydration fixture

This commit adds a first pass at a fixture that makes it easier to
debug the process of hydrating static markup. This is not complete:

1. It needs to be verified across multiple browsers
2. It needs to render with the current version of react

Still, it at least demonstrates the idea. A fixture like this will
also be helpful for debugging change events for hydrated inputs, which
presently do not fire if the user changes an input's text before
hydration.

* Tweak select width

* Manually join extra attributes in warning

This prevents a bug where Chrome reports `Array(n)` where `n` is the
size of the array.

* Transform with buble

* Eliminate dependencies

* Pull in react-live for better editing

* Handle encoding errors, pass react version

* Load the correct version of React

* Tweaks

* Revert style change

* Revert warning update

* Properly handle script errors. Fix dom-server CDN loading

* Fix 15.x releases

* Use postMessage to reduce latency, support older browsers

This commit makes a few tweaks to support older browsers and updates
the code transition process to use window.postMessage. This avoids
loading React on every single change.

* Fix fixture renamespacing bug

* Gracefully fallback to textarea in React 14

* Replace buble with babel, react-live with codemirror

* Simplify layout to resolve production code-mirror issues

* Tweak height rules for code-mirror

* Update theme to paraiso

* Format Code.js

* Adjust viewport to fix CodeMirror resize issue in production build

* Eliminate react-code-mirror

* Improve error state. Make full stack collapsable

* Add link to license in codemirror stylesheet

* Make code example more concise

* Replace "Hydrate" with "Auto-hydrate" for clarity

* Remove border below hydration header

* Rename query function in render.js

* Use Function(code) to evaluate hydration fixture

For clarity, and so that the Fixture component does not need to be
assigned to the window, this commit changes the way code is executed
such that it evaluates using a Function constructor.

* Extend hydration fixture to fill width. Design adjustments

This commit extends the hydration fixture such that it takes up the
full screen view. To accomplish this, the container that wraps all
fixtures has been moved to the FixtureSet component, utilized by all
other fixtures.

* Improve error scroll state

* Lazy load CodeMirror together before executing

This commit fixes an issue where CodeMirror wouldn't layout correctly
in production builds because the editor executes before the stylesheet
loaded. CodeMirror needs layout information, and was rendering
off-screen without correct CSS layout measurements.

* Fix indentation on error message

* Do not highlight errors from Babel. Add setPrototypeOf polyfill

This commit fixes an error in Safari 7.1 where Chalk highlighted Babel
errors caused a crash when setPrototypeOf was called within the
library.

This is also an issue on IE9, however this fix does not resolve issues
in that browser.

* Increase resilience to bad errors in Hydration fixture

- Reverts highlighting change. Polyfilling Safari 7.1 is sufficient
- Do not render a details tag in IE9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants