-
-
Notifications
You must be signed in to change notification settings - Fork 422
feat(metro): add Metro 0.83 compatibility layer #4408
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@module-federation/metro": patch | ||
| --- | ||
|
|
||
| Add Metro 0.83 compatibility layer. Metro 0.83 introduced a restrictive `exports` field that only allows `metro/private/*` paths instead of direct `metro/src/*` imports. This adds a `metro-compat` utility that dynamically resolves the correct import path, ensuring compatibility with both Metro 0.82 and 0.83+. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| /** | ||
| * Metro Compatibility Layer | ||
| * | ||
| * Provides backwards-compatible imports for Metro 0.82 and 0.83+ | ||
| * | ||
| * Metro 0.83 introduced a restrictive `exports` field that only allows | ||
| * `metro/private/*` paths instead of direct `metro/src/*` imports. | ||
| * | ||
| * This module dynamically resolves the correct import path based on the | ||
| * installed Metro version, ensuring compatibility with both versions. | ||
| */ | ||
|
|
||
| /** | ||
| * Attempts to import from Metro 0.83 format first, falls back to 0.82 format | ||
| */ | ||
| function tryImport(metro83Path: string, metro82Path: string) { | ||
| try { | ||
| return require(metro83Path); | ||
| } catch { | ||
| return require(metro82Path); | ||
| } | ||
| } | ||
|
|
||
| function getDefaultExport(mod: any) { | ||
| // CJS interop: if the module has a .default that is a function or object, use it | ||
| // Otherwise return the module itself (already the direct export) | ||
| if (mod != null && typeof mod === 'object' && 'default' in mod) { | ||
| return mod.default; | ||
| } | ||
| return mod; | ||
| } | ||
|
|
||
| // Server class | ||
| export const Server = getDefaultExport( | ||
| tryImport('metro/private/Server', 'metro/src/Server'), | ||
| ); | ||
|
|
||
| // DeltaBundler Serializers | ||
| export const baseJSBundle = getDefaultExport( | ||
| tryImport( | ||
| 'metro/private/DeltaBundler/Serializers/baseJSBundle', | ||
| 'metro/src/DeltaBundler/Serializers/baseJSBundle', | ||
| ), | ||
| ); | ||
|
|
||
| // Utility classes | ||
| export const CountingSet = getDefaultExport( | ||
| tryImport('metro/private/lib/CountingSet', 'metro/src/lib/CountingSet'), | ||
| ); | ||
|
|
||
| // Bundle utilities | ||
| export const bundleToString = getDefaultExport( | ||
| tryImport('metro/private/lib/bundleToString', 'metro/src/lib/bundleToString'), | ||
| ); | ||
|
|
||
| const relativizeSourceMapModule = tryImport( | ||
| 'metro/private/lib/relativizeSourceMap', | ||
| 'metro/src/lib/relativizeSourceMap', | ||
| ); | ||
| export const relativizeSourceMapInline = | ||
| relativizeSourceMapModule.relativizeSourceMapInline || | ||
| getDefaultExport(relativizeSourceMapModule); | ||
|
|
||
| // Re-export types - these come from metro/src/shared/types in both versions | ||
| // The types themselves are available through the main 'metro' package export | ||
| export type { RequestOptions, OutputOptions } from 'metro/src/shared/types'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We still import types from
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually after taking a closer look at this:
we should be fine with this as it is 👍 |
||
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.
Can we narrow this catch a bit? Right now we fallback on any error. If
metro/private/*exists but throws for another reason, we’ll mask the real issue. Maybe only fallback forMODULE_NOT_FOUNDfor that private path ?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.
good point, we could change this to
require.resolvefollowed byrequire👍