-
Notifications
You must be signed in to change notification settings - Fork 105
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
What happened?
I'm using the @rnx-kit/metro-serializer
package within my metro config, which extends the @expo/metro-config
. When running the bundler using npx expo start
everything works as expected. But if I try to run npx expo export --platform <android|ios>
I get the following error
Error: Serializer did not return expected format. The project copy of `expo/metro-config` may be out of date. Error: Unexpected token 'v', "var __BUND"... is not valid JSON`
Once I remove the MetroSerializer
, the npx expo export
command works as expected. I think this is happening due to Expo also requiring a custom serializer. One idea I had was to run both serializers and merge the results, not sure whether this will even work.
customSerializer: async (entryPoint, preModules, graph, options) => {
const expoSerializer = await config.serializer.customSerializer(
entryPoint,
preModules,
graph,
options,
);
const metroSerializer = await MetroSerializer([
CyclicDependencies({
includeNodeModules: false,
linesOfContext: 1,
throwOnError: process.env.CI === 'true',
}),
DuplicateDependencies({
// List of packages that should be ignored for duplicates check
ignoredModules: [
'isarray',
'duplexify',
'url',
'safe-buffer',
'string_decoder',
'readable-stream',
'entities',
'escape-string-regexp',
'tslib',
'buffer',
'punycode',
'promise',
'scheduler',
'@wry/trie',
'ansi-styles',
'color-convert',
'color-name',
'prop-types',
'base-64',
'inherits',
'util',
'color',
'qs',
'deepmerge',
'events',
'uuid',
'nanoid',
'fuse.js',
'hash-base',
'bn.js',
],
throwOnError: process.env.CI === 'true',
}),
])(entryPoint, preModules, graph, options);
return metroSerializer;
},
Here is my full metro config
/* eslint-disable no-console */
/**
* Metro configuration for React Native
* https://github.com/facebook/react-native
*
* @format
*/
const { getSentryExpoConfig } = require('@sentry/react-native/metro');
const path = require('path');
const projectRoot = __dirname;
const monorepoRoot = path.resolve(projectRoot, '../..');
const config = getSentryExpoConfig(projectRoot);
const {
wrapWithReanimatedMetroConfig,
} = require('react-native-reanimated/metro-config');
const {
makeMetroConfig,
resolveUniqueModule,
exclusionList,
} = require('@rnx-kit/metro-config');
const { MetroSerializer } = require('@rnx-kit/metro-serializer');
const {
CyclicDependencies,
} = require('@rnx-kit/metro-plugin-cyclic-dependencies-detector');
const {
DuplicateDependencies,
} = require('@rnx-kit/metro-plugin-duplicates-checker');
const env = process.env.ENV;
if (env) console.log(`Starting Metro Bundler with ${env} environment`);
let sourceExts = config.resolver.sourceExts;
// Used for mock and env file splitting
sourceExts = [
`${env}.ts`,
`${env}.tsx`,
`${env}.js`,
`${env}.jsx`,
...sourceExts,
];
if (process.env.E2E) {
sourceExts = ['e2e.ts', ...sourceExts];
}
// List of packages that should be resolved to a single instance
const singleInstancePackages = [
'@callstack/react-theme-provider',
'@smithy/util-hex-encoding',
'@smithy/is-array-buffer',
'@smithy/util-buffer-from',
'@smithy/util-utf8',
'@smithy/types',
'react-is',
'@sentry-internal/replay',
'@react-native/normalize-colors',
'use-latest-callback',
'@sentry/core',
'@sentry/react',
'@sentry/browser',
'@sentry-internal/browser-utils',
'@sentry-internal/replay-canvas',
'@sentry-internal/feedback',
'create-hash',
'ripemd160',
'@storybook/core',
'storybook',
'fast-deep-equal',
];
const { extraNodeModules, blockList } = singleInstancePackages.reduce(
(acc, curr) => {
const [pkgPath, pkgExcludePattern] = resolveUniqueModule(curr);
const blockListArr = [...acc.blockListArr, pkgExcludePattern];
const blockList = exclusionList(blockListArr);
return {
extraNodeModules: { ...acc.extraNodeModules, pkgPath },
blockListArr,
blockList,
};
},
{ extraNodeModules: {}, blockListArr: [], blockList: new RegExp('') },
);
let finalConfig = wrapWithReanimatedMetroConfig(
makeMetroConfig({
...config,
watchFolders: [monorepoRoot],
resolver: {
...config.resolver,
extraNodeModules: {
...require('node-libs-react-native'), // Make all core node modules available
tls: require.resolve('react-native-tcp-socket'),
...config.resolver.extraNodeModules,
...extraNodeModules,
},
blockList: [blockList, config.resolver.blockList, /.*\/db.devices.json/],
nodeModulesPaths: [
path.resolve(projectRoot, 'node_modules'),
path.resolve(monorepoRoot, 'node_modules'),
],
sourceExts: sourceExts,
resolverMainFields: ['react-native', 'browser', 'main'],
unstable_enableSymlinks: true,
unstable_enablePackageExports: true,
unstable_conditionNames: ['browser', 'require', 'react-native'], // axios package won't work without 'browser': https://github.com/facebook/react-native/issues/38025
},
serializer: {
...config.serializer,
// Integration of rnx-kit plugins
// https://microsoft.github.io/rnx-kit/docs/tools/metro-serializer
customSerializer: MetroSerializer([
CyclicDependencies({
includeNodeModules: false,
linesOfContext: 1,
throwOnError: process.env.CI === 'true',
}),
DuplicateDependencies({
// List of packages that should be ignored for duplicates check
ignoredModules: [
'isarray',
'duplexify',
'url',
'safe-buffer',
'string_decoder',
'readable-stream',
'entities',
'escape-string-regexp',
'tslib',
'buffer',
'punycode',
'promise',
'scheduler',
'@wry/trie',
'ansi-styles',
'color-convert',
'color-name',
'prop-types',
'base-64',
'inherits',
'util',
'color',
'qs',
'deepmerge',
'events',
'uuid',
'nanoid',
'fuse.js',
'hash-base',
'bn.js',
],
throwOnError: process.env.CI === 'true',
}),
]),
},
}),
);
if (env === 'storybook') {
const withStorybook = require('@storybook/react-native/metro/withStorybook');
finalConfig = withStorybook(config, {
// set to false to disable storybook specific settings
// you can use an env variable to toggle this
enabled: true,
// path to your storybook config folder
configPath: path.resolve(__dirname, './.storybook'),
});
}
module.exports = finalConfig;
Affected Package
@rnx-kit/metro-serializer
Version
2.0.0
Which platforms are you seeing this issue on?
- Android
- iOS
- macOS
- Windows
System Information
System:
OS: macOS 15.5
CPU: (12) arm64 Apple M2 Max
Memory: 895.63 MB / 32.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 22.15.0
path: ~/.nvm/versions/node/v22.15.0/bin/node
Yarn:
version: 4.7.0
path: ~/.nvm/versions/node/v22.15.0/bin/yarn
npm:
version: 11.3.0
path: ~/.nvm/versions/node/v22.15.0/bin/npm
Watchman:
version: 2025.03.10.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.16.2
path: /Users/aw17732/.gem/ruby/3.1.0/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 24.5
- iOS 18.5
- macOS 15.5
- tvOS 18.5
- visionOS 2.5
- watchOS 11.5
Android SDK:
API Levels:
- "31"
- "32"
- "33"
- "34"
- "35"
- "36"
Build Tools:
- 30.0.3
- 31.0.0
- 33.0.0
- 33.0.1
- 34.0.0
- 35.0.0
- 35.0.1
- 36.0.0
System Images:
- android-33 | Wear OS 4 ARM 64 v8a
- android-33 | Google Play ARM 64 v8a
- android-34 | Google APIs ARM 64 v8a
- android-34 | Google Play ARM 64 v8a
- android-35 | Google APIs ARM 64 v8a
- android-36 | Google APIs ARM 64 v8a
- android-36 | Google Play ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2025.1 AI-251.25410.109.2511.13752376
Xcode:
version: 16.4/16F6
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.10
path: /Users/aw17732/.sdkman/candidates/java/current/bin/javac
Ruby:
version: 3.1.7
path: /opt/homebrew/opt/[email protected]/bin/ruby
npmPackages:
"@react-native-community/cli": Not Found
react: Not Found
react-native: Not Found
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: true
newArchEnabled: true
Steps to Reproduce
- Create a default Expo metro config based on the docs https://docs.expo.dev/guides/customizing-metro/
- Add the custom metro serializer to the config
customSerializer: MetroSerializer([])
- Run
npx expo export --platform android
Code of Conduct
- I agree to follow this project's Code of Conduct
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working