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
Copy file name to clipboardExpand all lines: proposals/0534-metro-package-exports-support.md
+26-10Lines changed: 26 additions & 10 deletions
Original file line number
Diff line number
Diff line change
@@ -89,6 +89,7 @@ The following features and considerations are detailed in this section:
89
89
-[Conditional exports: `"import"` and `"require"`](#conditional-exports-import-and-require)
90
90
-[Conditional exports: Community definitions and `"browser"`](#conditional-exports-community-definitions-and-browser)
91
91
-[Conditional exports: User conditions and configuration](#conditional-exports-user-conditions-and-configuration)
92
+
-[Asset resolutions](#asset-resolutions)
92
93
-[Opting into strict `"exports"` handling](#opting-into-strict-exports-handling)
93
94
94
95
The following features will be implemented without any anticipated behaviour differences or special notes (links go to Node.js spec):
@@ -223,7 +224,7 @@ import BazComponent from './BazComponent.mjs';
223
224
224
225
-**Breaking**: Under `"exports"`, Metro will not resolve platform-specific extensions for listed package entry points.
225
226
- When resolving any import specifier:
226
-
- If the package defines `"exports"` and the import specifier (after expanding `sourceExts`) is matched, the package-defined path mapping will be used with no further transformation.
227
+
- If the package defines `"exports"` and the exact import specifier is matched, the package-defined path mapping will be used with no further transformation.
227
228
- If there is no match in`"exports"`, Metro will look for files which match the import specifier, trying all extension variants (existing resolution logic).
228
229
- With this decision, we will have narrowed support for platform-specific extensions inpackages. We will communicate to React Native package authors that alternative patterns should be used.
229
230
- We have no near-term plans to drop platform-specific extensions for packages not using `"exports"`, or in app code.
@@ -233,8 +234,10 @@ Note: We may yet (unplanned) independently make the platform-specific extensions
233
234
234
235
#### Illustrated
235
236
236
-
```json
237
+
```js
237
238
"exports": {
239
+
// Node.js recommends that packages list extensionless specifiers
240
+
// for compatibility
238
241
"./FooComponent": "./src/FooComponent.js",
239
242
"./FooComponent.js": "./src/FooComponent.js",
240
243
}
@@ -244,6 +247,7 @@ Import specifiers listed in `"exports"` will be used when matched. Alternative p
244
247
245
248
```js
246
249
import FooComponent from 'pkg/FooComponent';
250
+
// (Metro will not expand this specifier using sourceExts)
247
251
// Reads from "exports":
248
252
// pkg/src/FooComponent.js
249
253
@@ -389,14 +393,10 @@ module.exports = {
389
393
// (default: ['react-native'])
390
394
conditionNames: ['react-native', 'production'],
391
395
392
-
// A function that will be used to assert additional
393
-
// condition names when resolving an exports field path
394
-
getAssertedConditions: ({ platform }) => {
395
-
if (platform === 'web') {
396
-
return ['browser'];
397
-
}
398
-
399
-
return [];
396
+
// The set of additional condition names to dynamically
397
+
// assert by platform
398
+
conditionsByPlatform: {
399
+
web: ['browser'],
400
400
},
401
401
},
402
402
};
@@ -406,6 +406,22 @@ The exact name and shape of these options may change during implementation. Nami
406
406
407
407
In addition, `resolver.resolveRequest` will continue to provide an escape hatch from Metro's handling of conditional exports, should an app need to override imports from a given package.
408
408
409
+
### Asset resolutions
410
+
411
+
In addition to source files, Metro supports the concept of *asset files*. In addition to being bundled separately, asset files may have different resolution suffixes (configured via `resolver.assetResolutions`), for example `./img/check.png` may resolve a set of files that includes `./img/check@2x.png`, selected depending on target device.
412
+
413
+
Since this concept is not expressible using the existing `"exports"` spec (see [Subpath patterns](#subpath-patterns)), it makes sense to add Metro-specific functionality to continue supporting this feature.
414
+
415
+
We support existing config options that can be provided to customise how asset resolution behaves. These should remain load-bearing whether a file is resolved via `"exports"` or by filesystem resolution:
- Handle asset resolutions by calling `isAssetFile` on the subpath mapped to by `"exports"`. If this returns `true`, then expand asset resolutions by calling `resolveAsset` against this path.
423
+
- As with source files, if a subpath is not matched in `"exports"` and falls back to legacy resolution, a package encapsulation warning will be logged (using the base file name).
424
+
409
425
### Additional consideration: Jest
410
426
411
427
Because Metro's implementation of`"exports"` will not be strict, package resolution behaviour will be misaligned between Metro and Jest (where support was [added in Jest 28](https://jestjs.io/blog/2022/04/25/jest-28#packagejson-exports)). In projects consuming several exports-enabled dependencies, it is likely that misalignments will lead to confusing test failures.
0 commit comments