metro.config.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. const { getDefaultConfig } = require("expo/metro-config");
  2. const path = require("path");
  3. // Monorepo root
  4. const workspaceRoot = path.resolve(__dirname, "../..");
  5. const projectRoot = __dirname;
  6. const config = getDefaultConfig(projectRoot);
  7. // Watch the entire monorepo so changes in packages/ are picked up
  8. config.watchFolders = [workspaceRoot];
  9. // Resolve modules from both the project and monorepo root
  10. config.resolver.nodeModulesPaths = [
  11. path.resolve(projectRoot, "node_modules"),
  12. path.resolve(workspaceRoot, "node_modules"),
  13. ];
  14. // Force shared dependencies to always resolve from the project's node_modules.
  15. // This is necessary in pnpm monorepos where Metro follows symlinks into .pnpm/
  16. // and then resolves peer deps from the wrong location.
  17. const forcedDeps = {
  18. react: require.resolve("react", { paths: [projectRoot] }),
  19. "react-native": require.resolve("react-native", { paths: [projectRoot] }),
  20. };
  21. const originalResolveRequest = config.resolver.resolveRequest;
  22. config.resolver.resolveRequest = (context, moduleName, platform) => {
  23. // Intercept imports of shared deps and force them to the project's copy
  24. if (forcedDeps[moduleName]) {
  25. return {
  26. filePath: forcedDeps[moduleName],
  27. type: "sourceFile",
  28. };
  29. }
  30. // Fall back to default resolution
  31. if (originalResolveRequest) {
  32. return originalResolveRequest(context, moduleName, platform);
  33. }
  34. return context.resolveRequest(context, moduleName, platform);
  35. };
  36. module.exports = config;