Skip to content

Commit dbc06cf

Browse files
Use a module request for asyncRequireModulePath so Metro's transform cache is shareable across checkouts
@react-native/metro-config set asyncRequireModulePath with require.resolve(), which embeds the absolute path of the checkout in Metro's global transform cache key. Two checkouts of the same project (git worktrees, CI workspaces) never shared a transform cache entry. Add a react-native/async-require secondary entry point, like react-native/asset-registry, and point the config at it: a module request that resolves from any module in the project, hoisted or not, because react-native is the app's direct dependency and depends on metro-runtime itself.
1 parent 3718f62 commit dbc06cf

4 files changed

Lines changed: 33 additions & 2 deletions

File tree

packages/eslint-plugin-react-native/no-deep-imports.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ module.exports = {
201201

202202
return (
203203
source.value === 'react-native/asset-registry' ||
204+
source.value === 'react-native/async-require' ||
204205
source.value === 'react-native/react-private-interface' ||
205206
source.value === 'react-native/setup-env' ||
206207
source.value === 'react-native/unstable-internals-do-not-use'

packages/metro-config/src/index.flow.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ export function getDefaultConfig(projectRoot: string): ConfigT {
8585
transformer: {
8686
allowOptionalDependencies: true,
8787
assetRegistryPath: 'react-native/asset-registry',
88-
asyncRequireModulePath:
89-
require.resolve('metro-runtime/src/modules/asyncRequire'),
88+
asyncRequireModulePath: 'react-native/async-require',
9089
babelTransformerPath:
9190
require.resolve('@react-native/metro-babel-transformer'),
9291
getTransformOptions: async () => ({

packages/react-native/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
"types": null,
5050
"default": "./src/asset-registry.js"
5151
},
52+
"./async-require": {
53+
"types": null,
54+
"default": "./src/async-require.js"
55+
},
5256
"./react-private-interface": {
5357
"types": null,
5458
"default": "./src/react-private-interface.js"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
* @format
9+
*/
10+
11+
'use strict';
12+
13+
// ----------------------------------------------------------------------------
14+
// react-native/async-require
15+
//
16+
// This is an untyped secondary entry point intended to be referenced from
17+
// Metro's `transformer.asyncRequireModulePath` config option. Metro inlines
18+
// it into every module that uses `import()`, so it must be a module request
19+
// that resolves from any module in the project.
20+
//
21+
// Apps/libraries should not import this module; use `import()` instead.
22+
// ----------------------------------------------------------------------------
23+
24+
const asyncRequire = require('metro-runtime/src/modules/asyncRequire');
25+
26+
// eslint-disable-next-line @react-native/monorepo/no-commonjs-exports
27+
module.exports = asyncRequire;

0 commit comments

Comments
 (0)