-
Notifications
You must be signed in to change notification settings - Fork 47.2k
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
Drop Haste #11303
Drop Haste #11303
Conversation
b12a4f6
to
a5a9e5d
Compare
...goes on to list only benefits. |
I'll write something more comprehensive when I get it working :-) |
f44aa96
to
fc8bd83
Compare
I don't understand what CI failure means. It builds locally. But on the server |
This uncovered an interesting problem where ./b from package/src/a would resolve to a different instantiation of package/src/b in Jest. Either this is a showstopper or we can solve it by completely fobbidding remaining /src/.
It seems we can't use relative requires in tests anymore. Otherwise Jest becomes confused between real file and symlink. jestjs/jest#3830 This seems bad... Except that we already *don't* want people to create tests that import individual source files. All existing cases of us doing so are actually TODOs waiting to be fixed. So perhaps this requirement isn't too bad because it makes bad code looks bad. Of course, if we go with this, we'll have to lint against relative requires in tests. It also makes moving things more painful.
Shouldn't affect correctness (they were ignored) but fixes DEV size regression.
Should be ready for initial review. |
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 is a pretty large change-set. I skimmed it, paying more attention to the bits in scripts/rollup
.
I also did a build-and-sync locally and ran Catalyst with it for a couple of minutes. Had to update ReactNative.js
to point to the new haste module name (ReactNativeFiber-*
-> ReactNativeRenderer-*
) but otherwise it seemed...ok. (I would expect this sort of change to fail fast and hard, if it broke things.)
Left a couple of minor thoughts. Overall this looks like a nice cleanup. 👍
// TODO: direct imports like some-package/src/* are bad. Fix me. | ||
const { | ||
injectInternals, | ||
} = require('react-reconciler/src/ReactFiberDevToolsHook'); |
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.
How do you feel about adding a lint rule for this?
Something like...
export default function(context) {
return {
Identifier(node) {
if (node.name === 'require') {
const path = node.parent.arguments[0].value;
if (path.match(/^react.*\/src/)) {
context.report(node, 'Do not import project internals');
}
}
}
};
};
This would make us less likely to add more of these.
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.
Yea, definitely. On todo list above after we know the change itself works.
|
||
// Module provided by RN: |
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.
👍
@@ -0,0 +1 @@ | |||
module.exports = require('ReactCurrentOwner'); |
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.
Note to self: I don't understand the purpose of scripts/rollup/shims/rollup/*
Update: Looks like it maps to a combination of forkedFBModules
and getShims
in modules.js
. Still not entirely sure why it's necessary. Seems like it's related some some quirk/limitation of Rollup?
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 should be comments close to getShims and its usage explaining.
The object-assign shim replaces object-assign reference in anything that depends on React with assign implementation exposed on React internals. This avoids ReactDOM UMD having to ship its own polyfill of object-assign while React UMD already includes one.
We use the www shims for overriding some modules in React. Basically we want to have some requires be "untouched" and actually require modules from www instead of our implementations in the open source. We can't just tell Rollup to turn require('react/src/ReactCurrentOwner')
into require('ReactCurrentOwner')
because then it will attempt to resolve it (and not find it). The trick with a shim file and a separate plugin to "transform" the original file to null in memory is the only reliable way I found to completely "rewire" these requires to external modules in Rollup.
Some of these hacks might fall away or become simpler after ES modules. CommonJS is afterthought in Rollup and it breaks some more unusual cases. It might be that we're in that territory, and migrating to ESM will allow to revisit and simplify those hacks.
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.
Yeah, I saw the comments. I just didn't fully understand them I guess. The third paragraph above helps me understand a little.
scripts/rollup/bundles.js
Outdated
}, | ||
|
||
/******* React DOM *******/ | ||
{ | ||
babelOpts: babelOptsReact, | ||
label: 'dom-fiber', |
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 drop the -fiber
suffix from these now?
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 wanted to do in a follow up pass renaming those. Ideally I want this to be explicit and just use package names instead of labels. But that makes yarn build react
match everything. Maybe it had to be exact match but then it's more typing. I figured let's update these later when we have a better idea of how to do this ergonomically. Not coupled to build changes per se.
entry: 'react-art', | ||
global: 'ReactART', | ||
externals: ['react'], | ||
babel: opts => |
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.
nit: This could have a more meaningful name? Maybe like babelOptionsHook
? I dunno. Names are hard.
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'll probably do another pass renaming them in this PR. I oscillated between long and short names here and used short ones. But maybe I was just tired of complex config and tried to simplify the perception by using shorter words. I don't care strongly either way and will think about them again.
scripts/rollup/build.js
Outdated
@@ -503,44 +507,68 @@ function createBundle(bundle, bundleType) { | |||
} | |||
} | |||
|
|||
const filename = getFilename(bundle.name, bundle.hasteName, bundleType); | |||
const filename = getFilename( | |||
bundle.output || bundle.entry, |
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.
Looks like this only exists to map react-dom/server
to react-dom/server.node
Couldn't we simplify by just renaming react-dom/server.js
to react-dom/server.node.js
?
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.
Probably yes. I wanted to avoid an explicit separate entry point because it feels like public API. But I guess we have .browser
anyway so might as well do that.
Moved other follow up items into #11275. This is getting pretty painful to keep up to date now so I'd prefer landing and addressing follow ups later this week. |
That's fine of course 👍 I'm always happy to iterate on stuff like that. |
* Use relative paths in packages/react * Use relative paths in packages/react-art * Use relative paths in packages/react-cs * Use relative paths in other packages * Fix as many issues as I can This uncovered an interesting problem where ./b from package/src/a would resolve to a different instantiation of package/src/b in Jest. Either this is a showstopper or we can solve it by completely fobbidding remaining /src/. * Fix all tests It seems we can't use relative requires in tests anymore. Otherwise Jest becomes confused between real file and symlink. jestjs/jest#3830 This seems bad... Except that we already *don't* want people to create tests that import individual source files. All existing cases of us doing so are actually TODOs waiting to be fixed. So perhaps this requirement isn't too bad because it makes bad code looks bad. Of course, if we go with this, we'll have to lint against relative requires in tests. It also makes moving things more painful. * Prettier * Remove @providesModule * Fix remaining Haste imports I missed earlier * Fix up paths to reflect new flat structure * Fix Flow * Fix CJS and UMD builds * Fix FB bundles * Fix RN bundles * Prettier * Fix lint * Fix warning printing and error codes * Fix buggy return * Fix lint and Flow * Use Yarn on CI * Unbreak Jest * Fix lint * Fix aliased originals getting included in DEV Shouldn't affect correctness (they were ignored) but fixes DEV size regression. * Record sizes * Fix weird version in package.json * Tweak bundle labels * Get rid of output option by introducing react-dom/server.node * Reconciler should depend on prop-types * Update sizes last time
* Use relative paths in packages/react * Use relative paths in packages/react-art * Use relative paths in packages/react-cs * Use relative paths in other packages * Fix as many issues as I can This uncovered an interesting problem where ./b from package/src/a would resolve to a different instantiation of package/src/b in Jest. Either this is a showstopper or we can solve it by completely fobbidding remaining /src/. * Fix all tests It seems we can't use relative requires in tests anymore. Otherwise Jest becomes confused between real file and symlink. jestjs/jest#3830 This seems bad... Except that we already *don't* want people to create tests that import individual source files. All existing cases of us doing so are actually TODOs waiting to be fixed. So perhaps this requirement isn't too bad because it makes bad code looks bad. Of course, if we go with this, we'll have to lint against relative requires in tests. It also makes moving things more painful. * Prettier * Remove @providesModule * Fix remaining Haste imports I missed earlier * Fix up paths to reflect new flat structure * Fix Flow * Fix CJS and UMD builds * Fix FB bundles * Fix RN bundles * Prettier * Fix lint * Fix warning printing and error codes * Fix buggy return * Fix lint and Flow * Use Yarn on CI * Unbreak Jest * Fix lint * Fix aliased originals getting included in DEV Shouldn't affect correctness (they were ignored) but fixes DEV size regression. * Record sizes * Fix weird version in package.json * Tweak bundle labels * Get rid of output option by introducing react-dom/server.node * Reconciler should depend on prop-types * Update sizes last time
TODO
Not sure how I feel about this.
This helps enforce that we have proper module boundaries between packages. It already exposes some renderers read directly from reconciler (and thus won't be accessible to third party renderers). So I think that is kind of nice.
This exposed an interesting issue with Jest and Yarn Workspaces (jestjs/jest#3830).
In a test,
../createReactNativeComponentClass
andrequire('react-native-renderer').__SECRET_INTERNALS_DO_NOT_USE.createReactNativeComponentClass
will be two different things. Because one is imported relatively (and thus is "located" inpackages
) while the other one is instantiated from code path going vianode_modules/react-renderer
. Jest thinks they are different.This seemed like a show stopper to me at first. But then I thought, we don't like tests that do
../
anyway because they read internal modules. What if we just outlawed it?In this case, you'd have to write
react-native-renderer/src/createReactNativeComponentClass
to get it in a test. Or read it from a secret bag exposed onreact-native-renderer
. But that might actually be okay because it makes "bad" code looks bad. All existing cases of this already have TODOs next to them (#11299). So we could forbid relative requires in tests. Thus also encouraging people to write integration tests for new features too.We could also wait for Jest to fix it but I doubt that will happen soon since almost nobody else bumped into this.
Mostly seeking feedback if anyone has strong objections at this point. If not, I could further flatten the structure, forbid relative requires in tests, and then fix the build. I expect that Rollup configuration will be significantly simpler now that we can let it use Node resolving mechanism without silly whitelists like:
react/scripts/rollup/modules.js
Lines 32 to 50 in cc1ff87