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

[scheduler] 4/n Allow splitting out schedule in fb-www, prepare to fix polyfill issue internally #12900

Merged
merged 6 commits into from
May 29, 2018

Conversation

flarnie
Copy link
Contributor

@flarnie flarnie commented May 24, 2018

Edit: This PR has been rebased and no longer has an cruft from previous PRs.


what is the change?:

  • Uses references to global APIs instead of directly calling global APIs themselves inside of exported functions.
  • Shim the 'schedule' module itself in www, planning to use the generated bundle instead of inlining it.
  • Create a react-scheduler bundle for fb-www

why make this change?:
Context: internally we polyfill requestAnimationFrame and setTimeout and other global APIs. These "polyfills" also add and modify the functionality of the APIs, in ways that are not compatible with React.

We need more control over the version of those APIs that is used by the schedule module. To manage this, we want to try loading the schedule module before the polyfills are loaded, and holding a reference to the original requestAnimationFrame API.

To require schedule early we need to split it out from React. This diff takes a simple approach to that - we still want schedule bundled with React for open source, but internally we want it to be a separate module.

test plan:
I'll run the sync next week and verify that this all works. :)

issue:
See internal task T29442940

@sebmarkbage
Copy link
Collaborator

Why do we want it bundled in open source? Seems like the same thing can happen there, and we know that we'll need ART and DOM to probably coordinate.

@flarnie
Copy link
Contributor Author

flarnie commented May 24, 2018

Why do we want it bundled in open source? Seems like the same thing can happen there, and we know that we'll need ART and DOM to probably coordinate.

It will be useful to have this as a separate package in OS, after we finish implementing error handling, add proper docs, and have tried it with non-React code internally.

I should publish it with a similar README of warnings to simplecacheprovider but this seems like a quicker/safer first step.

@flarnie flarnie force-pushed the useReferencesToGlobalsInScheduler branch from 48fe169 to 3bc34c5 Compare May 24, 2018 21:26
@flarnie
Copy link
Contributor Author

flarnie commented May 25, 2018

@acdlite and @gaearon
My plan is to get this approved and then actually land and do the sync into www first thing next Tuesday, after the US holiday on Monday. :)

@flarnie flarnie force-pushed the useReferencesToGlobalsInScheduler branch 3 times, most recently from 3707b89 to de54d2e Compare May 25, 2018 21:26
@pull-bot
Copy link

pull-bot commented May 25, 2018

ReactDOM: size: 🔺+0.1%, gzip: 🔺+0.2%

Details of bundled changes.

Comparing: 001f9ef...1320890

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.development.js +0.1% +0.1% 624.28 KB 624.81 KB 145.25 KB 145.39 KB UMD_DEV
react-dom.production.min.js 🔺+0.1% 🔺+0.2% 93.87 KB 93.92 KB 30.38 KB 30.43 KB UMD_PROD
react-dom.development.js +0.1% +0.1% 608.65 KB 609.18 KB 141.26 KB 141.38 KB NODE_DEV
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 92.37 KB 92.42 KB 29.37 KB 29.41 KB NODE_PROD
ReactDOM-dev.js -1.8% -2.0% 630.92 KB 619.75 KB 144 KB 141.07 KB FB_WWW_DEV
ReactDOM-prod.js -2.0% -2.3% 274.48 KB 268.93 KB 51.66 KB 50.49 KB FB_WWW_PROD

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js +0.1% +0.1% 406.25 KB 406.78 KB 90.63 KB 90.75 KB UMD_DEV
react-art.production.min.js 🔺+0.1% 🔺+0.1% 80.88 KB 80.93 KB 24.92 KB 24.94 KB UMD_PROD
react-art.development.js +0.2% +0.2% 332.11 KB 332.63 KB 71.69 KB 71.81 KB NODE_DEV
react-art.production.min.js 🔺+0.1% 🔺+0.2% 45.24 KB 45.3 KB 14.03 KB 14.06 KB NODE_PROD
ReactART-dev.js -3.3% -4.2% 337.61 KB 326.38 KB 71.07 KB 68.06 KB FB_WWW_DEV
ReactART-prod.js -3.8% -4.6% 147.55 KB 141.93 KB 25.42 KB 24.25 KB FB_WWW_PROD

react-scheduler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-scheduler.development.js +3.3% +2.4% 15.67 KB 16.19 KB 4.83 KB 4.95 KB UMD_DEV
react-scheduler.production.min.js 🔺+2.0% 🔺+3.7% 2.27 KB 2.31 KB 1.07 KB 1.11 KB UMD_PROD
react-scheduler.development.js +3.4% +2.5% 15.47 KB 16 KB 4.79 KB 4.91 KB NODE_DEV
react-scheduler.production.min.js 🔺+2.4% 🔺+3.4% 2.36 KB 2.42 KB 1.09 KB 1.13 KB NODE_PROD
ReactScheduler-dev.js n/a n/a 0 B 13.04 KB 0 B 4 KB FB_WWW_DEV
ReactScheduler-prod.js n/a n/a 0 B 6.6 KB 0 B 1.7 KB FB_WWW_PROD

Generated by 🚫 dangerJS

@flarnie flarnie force-pushed the useReferencesToGlobalsInScheduler branch from de54d2e to 4ac1a80 Compare May 26, 2018 23:21
now,
scheduleWork,
cancelScheduledWork,
} from 'react-scheduler/src/ReactScheduler';
Copy link
Collaborator

Choose a reason for hiding this comment

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

This indirection seems a bit complicated :-(

Do we want to keep this fork long term? Is there a better fix in mind? How will this ultimately work in open source when the package is ready?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is complicated, agreed.

Do we want to keep this fork long term? Is there a better fix in mind? How will this ultimately work in open source when the package is ready?

Here is my understanding of how it will work -

  • Once the schedule API is stable, we publish it as a separate module and make it a dependency of react-dom and react-art. In OS people just pull in the schedule bundle via npm, and it uses the native requestAnimationFrame.
  • We would still need something like this for the 'www' build of 'react-dom', because we still have the problem with our 'requestAnimationFrame' polyfill in 'www'. Some of the behavior of the polyfill doesn't work, but some of the custom behavior we still need. I think at that point we can get away with the following simpler approach in 'www':
    • we still require 'schedule' before the polyfill runs, which means 'schedule' pulls in the native rAF and uses it.
    • In 'www' we write a wrapper module that adds the 'timeSlice' wrapper to 'schedule' itself, which we still need, and React would grab the wrapped version. Not sure if we'll still need a fork/shim for that to work.

It took a lot of discussion to agree on this solution, I'm hesitant to go back to the drawing board when we have something that works.

Regarding my original solution of just shimming 'requestAnimationFrame' itself in our 'www' build - @sebmarkbage had concerns that we should not be using the polyfilled version of 'requestAnimationFrame' at all in 'www', and that the best way to avoid pulling in the polyfill was to require the schedule module before the polyfilling happens.

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, if we just wrap the 'callback' before we pass it into 'scheduleWork' at every single callsite, or even if we just expose a wrapped version of 'schedule' for non-React use within 'www', then I think we can still avoid a fork of 'schedule'. After we publish it as a separate module, that is.

// We capture a local reference to any global, in case it gets polyfilled after
// this module is initially evaluated.
// We want to be using a consistent implementation.
const localDate = Date;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: Remove the local prefix

const Date = window.Date;

// We capture a local reference to any global, in case it gets polyfilled after
// this module is initially evaluated.
// We want to be using a consistent implementation.
const localRequestAnimationFrame = requestAnimationFrame;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here

Copy link
Contributor Author

@flarnie flarnie May 29, 2018

Choose a reason for hiding this comment

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

edit: looking again, maybe it's not a Flow error if we do window.Date like you actually suggested. Still feels weird but less weird than const Date = Date;.


Just one thing - which I think is why I did this in the first place. It's a Flow error, and seems like bad practice, to use a variable name which is also a global keyword.

I could do RequestAnimationFrame but that seems easier to be confused about. The local prefix means this is the local variable holding a reference to that API.

flarnie added 5 commits May 29, 2018 12:52
**what is the change?:**
See title

**why make this change?:**
We want to avoid initially calling one version of an API and then later
accessing a polyfilled version.

**test plan:**
Run existing tests.
**what is the change?:**
In 'www' we want to reference the separate build of ReactScheduler,
which allows treating it as a separate module internally.

**why make this change?:**
We need to require the ReactScheduler before our rAF polyfill activates,
in order to customize which custom behaviors we want.

This is also a step towards being able to experiment with using it
outside of React.

**test plan:**
Ran tests, ran the build, and ran `test-build`.
**what is the change?:**
See title

**why make this change?:**
Splitting out the 'schedule' module allows us to load it before
polyfills kick in for rAF and other APIs.

And long term we want to split this into a separate module anyway, this
is a step towards that.

**test plan:**
I'll run the sync next week and verify that this all works. :)
@flarnie
Copy link
Contributor Author

flarnie commented May 29, 2018

There is a test failing locally, not sure why. Investigating now.

@flarnie
Copy link
Contributor Author

flarnie commented May 29, 2018

Ah - just needed to yarn install after rebasing.

@flarnie flarnie force-pushed the useReferencesToGlobalsInScheduler branch from 4ac1a80 to 1320890 Compare May 29, 2018 20:17
@flarnie flarnie merged commit ff724d3 into facebook:master May 29, 2018
flarnie added a commit to flarnie/react that referenced this pull request Jun 4, 2018
**what is the change?:**
Undid facebook#12837

**why make this change?:**
We originally forked rAF because we needed to pull in a particular
version of rAF internally at Facebook, to avoid grabbing the default
polyfilled version.

The longer term solution, until we can get rid of the global polyfill
behavior, is to initialize 'schedule' before the polyfilling happens.

Now that we have landed and synced
facebook#12900 successfully, we can
initialize 'schedule' before the polyfill runs.
So we can remove the rAF fork. Here is how it will work:

1. Land this PR on Github.
2. Flarnie will quickly run a sync getting this change into www.
3. We delete the internal forked version of
   'requestAnimationFrameForReact'.
4. We require 'schedule' in the polyfill file itself, before the
   polyfilling happens.

**test plan:**
Flarnie will manually try the above steps locally and verify that things
work.

**issue:**
Internal task T29442940
@flarnie flarnie mentioned this pull request Jun 4, 2018
flarnie added a commit to flarnie/react that referenced this pull request Jun 12, 2018
**what is the change?:**
Undid facebook#12837

**why make this change?:**
We originally forked rAF because we needed to pull in a particular
version of rAF internally at Facebook, to avoid grabbing the default
polyfilled version.

The longer term solution, until we can get rid of the global polyfill
behavior, is to initialize 'schedule' before the polyfilling happens.

Now that we have landed and synced
facebook#12900 successfully, we can
initialize 'schedule' before the polyfill runs.
So we can remove the rAF fork. Here is how it will work:

1. Land this PR on Github.
2. Flarnie will quickly run a sync getting this change into www.
3. We delete the internal forked version of
   'requestAnimationFrameForReact'.
4. We require 'schedule' in the polyfill file itself, before the
   polyfilling happens.

**test plan:**
Flarnie will manually try the above steps locally and verify that things
work.

**issue:**
Internal task T29442940
flarnie added a commit that referenced this pull request Jun 13, 2018
* Remove rAF fork

**what is the change?:**
Undid #12837

**why make this change?:**
We originally forked rAF because we needed to pull in a particular
version of rAF internally at Facebook, to avoid grabbing the default
polyfilled version.

The longer term solution, until we can get rid of the global polyfill
behavior, is to initialize 'schedule' before the polyfilling happens.

Now that we have landed and synced
#12900 successfully, we can
initialize 'schedule' before the polyfill runs.
So we can remove the rAF fork. Here is how it will work:

1. Land this PR on Github.
2. Flarnie will quickly run a sync getting this change into www.
3. We delete the internal forked version of
   'requestAnimationFrameForReact'.
4. We require 'schedule' in the polyfill file itself, before the
   polyfilling happens.

**test plan:**
Flarnie will manually try the above steps locally and verify that things
work.

**issue:**
Internal task T29442940

* fix nits

* fix tests, fix changes from rebasing

* fix lint
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.

6 participants