Skip to content

[standards] Umbrella issue to track migration to standard path-based requires (remove Haste) #24316

Closed
@ide

Description

@ide

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.


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 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:

import PanResponder from '../../vendor/react-native/PanResponder';
export default PanResponder;

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ☂️ UmbrellaTo label issues that serve as coordination point and drivers for tasks in the react-native repoPartnerResolution: LockedThis issue was locked by the bot.Type: DiscussionLong running discussion.p: ExpoPartner: Expo

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions