Symlinking metro.config breaks from Expo SDK 44 to 46. How to symlink in 46?

Viewed 51

I started a new mobile app project and since we have our own mobile components for reusability, we also use symlinking from the local component to the Expo app to make sure it's being developed properly. We have successfully linked prior Expo apps using SDK 44, but in this new project, we decided to use the most recent 46. It seems when I update the metro.config file the same as before, the bundler crashes.

default metro.config

const { getDefaultConfig } = require('expo/metro-config');
const path = require('path');

// const workspaceRoot = path.resolve(__dirname, '../myComponentLib');  // this gets uncommented when using a link
const defaultConfig = getDefaultConfig(__dirname);

defaultConfig.transformer.babelTransformerPath = require.resolve(
  'react-native-svg-transformer',
);

const assetExts = defaultConfig.resolver.assetExts;
const sourceExts = defaultConfig.resolver.sourceExts;

defaultConfig.resolver = {
  assetExts: assetExts.filter((ext) => ext !== 'svg'),
  sourceExts: [...sourceExts, 'svg'],
};
defaultConfig.resolver.nodeModulesPaths = [
  path.resolve(__dirname, 'node_modules'),
  // path.resolve(workspaceRoot, 'packages/mobile/node_modules'), // this gets uncommented when using a link
];
// defaultConfig.watchFolders = [path.resolve(workspaceRoot)]; // this gets uncommented when using a link

module.exports = defaultConfig;

When I use the metro.config like above, it's fine. But if I uncomment the 3 lines notes, it fails. The error I get is:

symlink failure

I am curious, is there a difference in linking between the different SDKs now?

1 Answers

Wow, the reason for this is hidden well inside the docs: https://docs.expo.dev/guides/monorepos/#modify-the-metro-config

Scroll down to the section:

Why do we need to watch all the files with the monorepo?

Their example to watch scoped package names does the trick:

// If your monorepo tooling can give you the list of monorepo workspaces linked
// in your app workspace, you can automate this list instead of hardcoding them.
const monorepoPackages = {
  '@acme/api': path.resolve(workspaceRoot, 'packages/api'),
  '@acme/components': path.resolve(workspaceRoot, 'packages/components'),
};
Related