You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue tracks commits that rewrite require() calls to use standard module paths instead of Haste module names. This brings the RN repo closer to how the React repo is set up, and also opens the door for greater compatibility with the last 10 years of tooling that uses path-based module locations, and eliminates the entire class of issues related to the Haste map outside of the Facebook context.
All modules in the RN repository will still be requireable via Haste. That is, if there's Facebook application code that uses Haste, there will be no change.
This is a spiritual continuation of #18598, which has more technical details.
In the 0.61 release of React Native, we are internally replacing "Haste"-style module imports with standard path-based imports. Instead of require('View'), React Native will internally use require('./View'). Haste is a proprietary module system with a global namespace that is used within Facebook. Path-based imports are used by browsers, Node.js, and various tools and libraries in the greater JavaScript ecosystem. Moving to the standard means React Native will be more compatible with the ecosystem. Also, this creates a path to optimize the bundling step, as the bundler no longer needs to scan all files to create the Haste module map.
Some out-of-tree implementations of other platforms, like React Native Windows, may be affected by this change if they rely on overriding files using overlapping Haste module names. There are two potential solutions for maintainers of platforms like this.
Vendoring React Native
One solution is to follow React Native for Web's approach of vendoring (copying) React Native's code into the out-of-tree platform repository. This approach is also more future-proof and works if React Native were to publish itself as a single "flat bundle" in the same manner as React, which would also be a breaking change for out-of-tree platform implementations. It also simplifies the work required if React Native were to rely on the JS interpreter's built-in import/export module system, which does not implement Haste.
React Native for Web's entry point (index.js) exports web-specific implementations of all the public APIs in React Native. But, sometimes, parts of React Native's code also run on the web without any changes. To share code with React Native, React Native for Web imports the code it vendored from React Native. For example, React Native for Web's implementation of PanResponder uses React Native's implementation:
Finally, React Native for Web provides a Babel plugin that rewrites all imports of react-native in your application code to import react-native-web instead. For example, import { View } from 'react-native' is rewritten to import { View } from 'react-native-web'.
React Native for Web's approach provides stability, as newly published patch versions of React Native -- which may have internal breaking changes despite keeping the public API unchanged -- will not affect the vendored code at all until the maintainer intentionally updates it.
Overriding imports with Babel
Another solution is to write a Babel plugin that rewrites imports to files that need to be overridden. For example, let's say an out-of-tree platform needs to override React Native's View.js and that the overriding file is under react-native-xx/View.xx.js. Using a Babel plugin, one can rewrite all imports of React Native's View.js to instead import react-native-xx/View.xx.js. This Babel plugin simulates the current behavior of overriding files using Haste.
This issue tracks commits that rewrite
require()calls to use standard module paths instead of Haste module names. This brings the RN repo closer to how the React repo is set up, and also opens the door for greater compatibility with the last 10 years of tooling that uses path-based module locations, and eliminates the entire class of issues related to the Haste map outside of the Facebook context.All modules in the RN repository will still be requireable via Haste. That is, if there's Facebook application code that uses Haste, there will be no change.
This is a spiritual continuation of #18598, which has more technical details.
[standards][flow] Set up .flowconfig to support Haste and path-based imports #24318[standards] Rewrite imports in RNTester to use standard paths #24317[standards] Migrate TurboModule example in RNTester to use path-based requires #24754[standards] Migrate "Libraries" from Haste to standard path-based requires (sans vendor & renderers) #24749,[standards] Replace more Haste imports with path-based imports #25001[standards] Migrate IntegrationTests from Haste to path-based requires #24750[standards] Migrate Jest setup scripts from Haste to path-based requires #24753[standards] Migrate "androidTest" JS from Haste to path-based requires #24813[standards] Migrate vendored JS from Haste to path-based imports #24769):[standards] Migrate vendored code from Haste to path-based imports #24807[standards] Migrate React renderers from Haste to path-based imports #24770):[standards] ReactPrivate, an explicit interface between the renderer and RN #24782,[react-native] Use path-based imports instead of Haste for the RN renderer react#15604,Sync React with Haste-style imports rewritten to use path-based imports instead #25100,[react-native] Rewrite Haste imports in RN shims and add .fb.js extension react#15786[standards] Migrate react-native-implementation.js from Haste to path-based imports #24771)[lint] Add a lint rule to disallow Haste imports #25058Jest hasteImpl, .flowconfig, Metro):[jest] Explicitly separate mocked native modules from mocked JS modules #24809(Jest mocks),[jest] Delete hasteImpl, providesModuleNodeModules, and modulePathNameMapper #24811(Jest hasteImpl),[standards] Make Flow configs use path-based imports instead of Haste #24812(.flowconfig),[breaking] Turn off providesModuleNodeModules by default metro#410(Metro default providesModuleNodeModules)Draft Announcement Notes
Replacing Haste with standard imports
In the 0.61 release of React Native, we are internally replacing "Haste"-style module imports with standard path-based imports. Instead of
require('View'), React Native will internally userequire('./View'). Haste is a proprietary module system with a global namespace that is used within Facebook. Path-based imports are used by browsers, Node.js, and various tools and libraries in the greater JavaScript ecosystem. Moving to the standard means React Native will be more compatible with the ecosystem. Also, this creates a path to optimize the bundling step, as the bundler no longer needs to scan all files to create the Haste module map.Some out-of-tree implementations of other platforms, like React Native Windows, may be affected by this change if they rely on overriding files using overlapping Haste module names. There are two potential solutions for maintainers of platforms like this.
Vendoring React Native
One solution is to follow React Native for Web's approach of vendoring (copying) React Native's code into the out-of-tree platform repository. This approach is also more future-proof and works if React Native were to publish itself as a single "flat bundle" in the same manner as React, which would also be a breaking change for out-of-tree platform implementations. It also simplifies the work required if React Native were to rely on the JS interpreter's built-in import/export module system, which does not implement Haste.
React Native for Web's entry point (
index.js) exports web-specific implementations of all the public APIs in React Native. But, sometimes, parts of React Native's code also run on the web without any changes. To share code with React Native, React Native for Web imports the code it vendored from React Native. For example, React Native for Web's implementation ofPanResponderuses React Native's implementation:Finally, React Native for Web provides a Babel plugin that rewrites all imports of
react-nativein your application code to importreact-native-webinstead. For example,import { View } from 'react-native'is rewritten toimport { View } from 'react-native-web'.React Native for Web's approach provides stability, as newly published patch versions of React Native -- which may have internal breaking changes despite keeping the public API unchanged -- will not affect the vendored code at all until the maintainer intentionally updates it.
Overriding imports with Babel
Another solution is to write a Babel plugin that rewrites imports to files that need to be overridden. For example, let's say an out-of-tree platform needs to override React Native's
View.jsand that the overriding file is underreact-native-xx/View.xx.js. Using a Babel plugin, one can rewrite all imports of React Native'sView.jsto instead importreact-native-xx/View.xx.js. This Babel plugin simulates the current behavior of overriding files using Haste.