Files
frontend/metro.config.js

82 lines
3.2 KiB
JavaScript
Raw Permalink Normal View History

/** @type {import('expo/metro-config').MetroConfig} */
const { getDefaultConfig } = require('expo/metro-config');
2026-04-13 01:30:37 +08:00
const path = require('path');
const config = getDefaultConfig(__dirname);
// Add wasm asset support
config.resolver.assetExts.push('wasm');
2026-04-13 01:30:37 +08:00
// Support TypeScript path aliases (@/ -> ./src/)
config.resolver.alias = {
'@': path.resolve(__dirname, 'src'),
};
// Ensure platform-specific files are resolved correctly
config.resolver.platforms = ['ios', 'android', 'native', 'web'];
// Web shims for native-only React Native APIs that don't exist in react-native-web.
// Packages like react-native-pager-view import codegenNativeComponent from
// react-native/Libraries/Utilities/codegenNativeComponent, which calls
// requireNativeComponent internally. On web (react-native-web), these APIs
// don't exist, causing "(0 , _reactNativeWebDistIndex.requireNativeComponent)
// is not a function".
const webShimPaths = [
'react-native/Libraries/Utilities/codegenNativeComponent',
'react-native/Libraries/Utilities/codegenNativeCommands',
'react-native/Libraries/Types/CodegenTypes',
'react-native/Libraries/ReactNative/requireNativeComponent',
];
// Packages that should be entirely replaced with web shims on web platform.
// These packages import requireNativeComponent directly from 'react-native'
// (which resolves to react-native-web on web) and don't have web implementations.
const webPackageShims = {
};
const originalResolveRequest = config.resolver.resolveRequest;
const shimDir = path.resolve(__dirname, 'web-shims');
config.resolver.resolveRequest = (context, moduleName, platform) => {
// Redirect entire native-only packages to web shims
if (platform === 'web' && webPackageShims[moduleName]) {
return {
type: 'sourceFile',
filePath: webPackageShims[moduleName],
};
}
// Redirect specific React Native internal modules to web shims
if (platform === 'web' && webShimPaths.some((p) => moduleName.endsWith(p))) {
// For requireNativeComponent, the path doesn't follow the Libraries/* pattern
if (moduleName.endsWith('react-native/Libraries/ReactNative/requireNativeComponent')) {
return {
type: 'sourceFile',
filePath: path.join(shimDir, 'react-native', 'Libraries', 'ReactNative', 'requireNativeComponent.js'),
};
}
const shimName = moduleName.replace('react-native/Libraries/', '');
return {
type: 'sourceFile',
filePath: path.join(shimDir, 'react-native', 'Libraries', shimName + '.js'),
};
}
if (originalResolveRequest) {
return originalResolveRequest(context, moduleName, platform);
}
return context.resolveRequest(context, moduleName, platform);
};
// NOTE: enhanceMiddleware is marked as deprecated in Metro's types,
// but there's currently no official alternative for custom dev server headers.
// For production, configure COEP/COOP headers on your hosting platform.
// These headers are required for SharedArrayBuffer (used by expo-sqlite on web).
config.server.enhanceMiddleware = (middleware) => {
return (req, res, next) => {
res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless');
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
middleware(req, res, next);
};
};
module.exports = config;