1'use strict';
2
3const { getDefaultConfig } = require('@expo/metro-config');
4const debug = require('debug')('workspaces');
5const findYarnWorkspaceRoot = require('find-yarn-workspace-root');
6const path = require('path');
7
8const getSymlinkedNodeModulesForDirectory = require('./common/get-symlinked-modules');
9
10/**
11 * Returns a configuration object in the format expected for "metro.config.js" files. The
12 * configuration:
13 *
14 *   * includes the Yarn workspace root in Metro's list of root directories
15 *   * resolves symlinked packages, namely workspaces
16 *   * excludes all modules from Haste's module system (providesModule)
17 *   * excludes modules in the native Android and Xcode projects
18 */
19exports.createMetroConfiguration = function createMetroConfiguration(projectPath, options) {
20  projectPath = path.resolve(projectPath);
21  debug(`Creating a Metro configuration for the project at %s`, projectPath);
22  const {
23    // Remove the React Native reporter.
24    reporter,
25    ...defaultConfig
26  } = getDefaultConfig(projectPath, options);
27
28  let watchFolders;
29  let extraNodeModules;
30
31  const workspaceRootPath = findYarnWorkspaceRoot(projectPath);
32  if (workspaceRootPath) {
33    debug(`Found Yarn workspace root at %s`, workspaceRootPath);
34    watchFolders = [workspaceRootPath];
35    extraNodeModules = {
36      ...getSymlinkedNodeModulesForDirectory(workspaceRootPath),
37      ...getSymlinkedNodeModulesForDirectory(projectPath),
38    };
39  } else {
40    debug(`Could not find Yarn workspace root`);
41    watchFolders = [];
42    extraNodeModules = getSymlinkedNodeModulesForDirectory(projectPath);
43  }
44
45  return {
46    ...defaultConfig,
47    // Search for modules from the project's root directory
48    projectRoot: projectPath,
49
50    // Include npm packages from the workspace root, where packages are hoisted
51    watchFolders,
52    resolver: {
53      ...defaultConfig.resolver,
54      // test-suite includes a db asset
55      assetExts: [...defaultConfig.resolver.assetExts, 'db'],
56
57      // Include .cjs files
58      sourceExts: [...defaultConfig.resolver.sourceExts, 'cjs'],
59
60      // Make the symlinked packages visible to Metro
61      extraNodeModules,
62
63      // Use Node-style module resolution instead of Haste everywhere
64      providesModuleNodeModules: [],
65
66      // Ignore test files and JS files in the native Android and Xcode projects
67      blockList: [
68        /\/__tests__\/.*/,
69        /.*\/android\/React(Android|Common)\/.*/,
70        /.*\/versioned-react-native\/.*/,
71      ],
72    },
73
74    transformer: {
75      ...defaultConfig.transformer,
76      // Ignore file-relative Babel configurations and apply only the project's
77      enableBabelRCLookup: false,
78    },
79  };
80};
81