-
Notifications
You must be signed in to change notification settings - Fork 47k
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 Reconciler Package #10758
React Reconciler Package #10758
Conversation
packages/react-reconciler/README.md
Outdated
@@ -0,0 +1,16 @@ | |||
# react |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
derp, probably need to do more than simply copy-paste this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some thoughts 😄
@@ -0,0 +1,38 @@ | |||
{ | |||
"name": "react-reconciler", | |||
"description": "React is a JavaScript library for building user interfaces.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prob needs better description?
fixtures/reconciler/README.md
Outdated
* `yarn install` | ||
* edit node_modules/react-reconciler/cjs/react-reconciler.development.js | ||
* Add the below snipper after `var valueStack = [];` | ||
* `yarn test` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem ideal that our test process involves editing content in node_modules
. I would expect to see something more like:
yarn install
yarn build
yarn test
Where the yarn build
step just runs yarn build -- reconciler
in the main project to build a copy of the reconciler.
Then the test file (index.js
I guess) should test something meaningful without any editing being required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idk if this needs to stick around or how to write a test that ensures that each reconciler has its own scope for reconciler-unique things like valueStack
other than this really hacky way.
Possibly something with actually creating two reconcilers and then making them both do work that would indicate if they were clobbering each other or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we could automate it. At this point I don't think it's important if we manually verify it works once.
packages/react-reconciler/README.md
Outdated
@@ -0,0 +1,16 @@ | |||
# react |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😁
fixtures/reconciler/package.json
Outdated
"private": true, | ||
"dependencies": { | ||
"react": "^16.0.0-", | ||
"react-reconciler": "file:../../build/packages/react-reconciler" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing prop-types
, fbjs
, and object-assign
dependencies?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷♂️ Everything worked okay for me so far. Idk if I even need those in the packages/react-reconciler
area. There’s also a rollup
warning right now for this package and apparently I broke bundling ReactDOM
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops. I thought I was looking at packages/react-reconciler/package.json
instead of the one in fixtures. Disregard. 😄
{ | ||
"name": "react-reconciler", | ||
"description": "React is a JavaScript library for building user interfaces.", | ||
"version": "16.0.0-rc.2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we version this separately? Regular changes to React will be breaking changes for the reconciler.
We should either start with 0.0.1
or 1.0.0
😄
scripts/rollup/build.js
Outdated
@@ -78,6 +78,7 @@ function getHeaderSanityCheck(bundleType, hasteName) { | |||
} | |||
|
|||
function getBanner(bundleType, hasteName, filename) { | |||
const isReconciler = /react-reconciler/.test(filename); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer a flag on the bundle, like we do for isRenderer
. Or, ideally, unify them under a required enum: 'isomorphic' | 'renderer' | 'reconciler'
. But unification can wait.
Looks like this broke the core build? |
cc-ing @sebmarkbage / @sophiebits from convo in #9103 in case you didn’t see this PR which is more or less the model Dan was referring to at #9103 (comment) |
scripts/rollup/build.js
Outdated
@@ -88,10 +89,15 @@ function getBanner(bundleType, hasteName, filename) { | |||
let banner = Header.getHeader(filename, reactVersion); | |||
// Wrap the contents of the if-DEV check with an IIFE. | |||
// Block-level function definitions can cause problems for strict mode. | |||
banner += `'use strict';\n\n\nif (process.env.NODE_ENV !== "production") {\n(function() {\n`; | |||
banner += isReconciler | |||
? `'use strict';\n\n\nif (process.env.NODE_ENV !== "production") {\nmodule.exports = function(config) {\n` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I'm being dense but I don't understand why the reconciler needs to be a special case here. Isn't ReactFiberReconciler's export already the function we want?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is, but this covers ensuring that all other modules with global-module state is created anew for each 3rd party reconciler instance until all internal modules with that state are wrapped in factory methods.
Only thing left that I know that would be nice is generating the |
Can you fix the CI? |
getting this error when prettier is ran. 🤔 |
packages/react-reconciler/README.md
Outdated
) { | ||
let root = container._reactRootContainer; | ||
if (!root) { | ||
const newRoot = Renderer.createContainer(container); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reconciler.createContainer(container);
?
packages/react-reconciler/README.md
Outdated
// Initial mount should not be batched. | ||
Renderer.unbatchedUpdates(() => { | ||
Renderer.updateContainer(element, newRoot, null, callback); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Renderer/Reconciler/g
?
Reconciler.unbatchedUpdates(() => {
Reconciler.updateContainer(element, newRoot, null, callback);
});
packages/react-reconciler/README.md
Outdated
Renderer.updateContainer(element, newRoot, null, callback); | ||
}); | ||
} else { | ||
Renderer.updateContainer(element, root, null, callback); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reconciler.updateContainer(element, root, null, callback);
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great eye, @koba04. thanks!
I don't think we call the result of calling the reconciler "a reconciler" :-) Sorry for the confusion. The result is a |
Agreed! "reconciler" may not be the most user-friendly name for the API. Just an idea, but what about something like import createReactRenderer from 'create-react-renderer';
const Renderer = createReactRenderer(config); |
I would imagine a |
scripts/rollup/modules.js
Outdated
// external modules tell Rollup that we should not attempt | ||
// to bundle these modules and instead treat them as | ||
// external depedencies to the bundle. so for CJS bundles | ||
// this means having a require("name-of-external-module") at | ||
// the top of the bundle. for UMD bundles this means having | ||
// both a require and a global check for them | ||
let externalModules = externals.slice(); | ||
const isRenderer = moduleType === RENDERER || moduleType === RECONCILER; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks counter-intuitive. I would probably replace
if (isRenderer) {
externalModules.push('react');
}
with
if (moduleType !== ISOMORPHIC) {
externalModules.push('react');
}
below.
scripts/rollup/modules.js
Outdated
@@ -97,7 +101,7 @@ function getNodeModules(bundleType, isRenderer) { | |||
return { | |||
// Bundle object-assign once in the isomorphic React, and then use | |||
// that from the renderer UMD. Avoids bundling it in both UMDs. | |||
'object-assign': isRenderer | |||
'object-assign': moduleType === RENDERER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should instead check for ISOMORPHIC
here, and reverse the ternary. Isomorphic gets the real thing, everyone else gets the shim. Even though technically we don’t have reconciler UMDs anyway.
I'd like to figure out a way to have a testing procedure that doesn't ask folks to edit |
Or, perhaps, we shouldn't focus on the context at all. After all this particular case can be fixed. If you manually verified wrapping it in a closure works (why wouldn't it), this should be enough for now. Instead we should have a fixture that lets us check that the reconciler package is not completely borked. For example by declaring a very simple renderer and writing a Node script that verifies it renders something. |
Do you want that done before this is merged? Two ideas:
|
I want to have some way to test it before this is merged since we're going to start doing releases very soon. I would suggest copy-pasting noop renderer and having a simple test that verifies it works. |
2b196c4
to
fa94122
Compare
Something like 2b196c4? It’s still not fully automatic so I could look into running the Also, |
I don't think we need to port the unit test. A simple smoke test verifying it doesn't instacrash rendering a simple component is enough. You can also delete all irrelevant code there. |
To make sure I’m understanding you, is something like this in the fixtures renderer what you’re thinking?
Do I need to tie that into any other command that is run during releases? |
@gaearon pinging in case you missed --^. Happy to make the change as soon as I know I’m doing what you expect 😄 |
Noop renderer renders to a tree in memory. It would just be nice to verify basic sanity of that tree. e.g. that it created "hello world" host instance. |
woohoo, just noticed this is live: https://www.npmjs.com/package/react-reconciler :) |
Alternative approach to #10641. Rather than create the entire packaging and bundling script this exposes the React Reconciler as a factory package so all private+global state is unique per reconciler which solves the original concerns raised by @gaearon in #9103 (comment).
I think it also solves the open question How should we handle React-specific stuff pretty well since it doesn’t change the current rollup/build script at this point.
I added a really cheap
fixtures/reconciler/*
directory that requires some manualnode_modules/react-reconciler/cjs/*.js
modifications to test for now, but did test both versions.This also (rather sloppily) modifies the
scripts/rollup
tasks to special case thereact-reconciler
wrapping.TODO:
react-reconciler.js.flow
file in the output package so external reconcilers can use flow for writing and maintaining reconcilers.cc @gaearon @bvaughn