1const createExpoWebpackConfigAsync = require('@expo/webpack-config'); 2const debug = require('debug')('workspaces'); 3const findYarnWorkspaceRoot = require('find-yarn-workspace-root'); 4const globModule = require('glob'); 5const path = require('path'); 6const util = require('util'); 7 8const glob = util.promisify(globModule); 9const getSymlinkedNodeModulesForDirectory = require('./common/get-symlinked-modules'); 10 11/** 12 * Returns a webpack configuration object that: 13 * 14 * * transpiles symlinked workspace packages 15 * * watches for file changes in symlinked packages 16 * * allows for additional custom packages to be transpiled via env.babel argument 17 */ 18exports.createWebpackConfigAsync = async function createWebpackConfigAsync(env, argv) { 19 const workspacePackagesToTranspile = []; 20 const workspaceRootPath = findYarnWorkspaceRoot(env.projectRoot); 21 22 if (workspaceRootPath) { 23 debug(`Found Yarn workspace root at %s`, workspaceRootPath); 24 25 const symlinkedModules = getSymlinkedNodeModulesForDirectory(workspaceRootPath); 26 const symlinkedModulePaths = Object.values(symlinkedModules); 27 const workspacePackage = require(path.resolve(workspaceRootPath, 'package.json')); 28 29 // discover workspace package directories via glob - source yarn: 30 // https://github.com/yarnpkg/yarn/blob/a4708b29ac74df97bac45365cba4f1d62537ceb7/src/config.js#L812-L826 31 const patterns = workspacePackage.workspaces?.packages ?? workspacePackage.workspaces ?? []; 32 const registryFilenames = 'package.json'; 33 const trailingPattern = `/+(${registryFilenames})`; 34 35 const files = await Promise.all( 36 patterns.map((pattern) => 37 glob(pattern.replace(/\/?$/, trailingPattern), { 38 cwd: workspaceRootPath, 39 ignore: `/node_modules/**/+(${registryFilenames})`, 40 }) 41 ) 42 ); 43 44 for (const file of new Set(files.flat())) { 45 const packageDirectory = path.join(workspaceRootPath, path.dirname(file)); 46 if (symlinkedModulePaths.includes(packageDirectory)) { 47 workspacePackagesToTranspile.push(packageDirectory); 48 } 49 } 50 } else { 51 debug(`Could not find Yarn workspace root`); 52 } 53 54 env.babel = env.babel ?? {}; 55 56 const config = await createExpoWebpackConfigAsync( 57 { 58 ...env, 59 babel: { 60 dangerouslyAddModulePathsToTranspile: [ 61 ...workspacePackagesToTranspile, 62 ...(env.babel.dangerouslyAddModulePathsToTranspile ?? []), 63 ], 64 }, 65 }, 66 argv 67 ); 68 69 // use symlink resolution so that webpack watches file changes 70 config.resolve.symlinks = true; 71 72 return config; 73}; 74