1import fs from 'fs'; 2import Server from 'metro/src/Server'; 3import output from 'metro/src/shared/output/bundle'; 4import type { BundleOptions } from 'metro/src/shared/types'; 5import path from 'path'; 6 7import { Options } from './resolveOptions'; 8import { Log } from '../../log'; 9import { loadMetroConfigAsync } from '../../start/server/metro/instantiateMetro'; 10import { importCliSaveAssetsFromProject } from '../../start/server/metro/resolveFromProject'; 11import { setNodeEnv } from '../../utils/nodeEnv'; 12import { getAssets } from '../fork-bundleAsync'; 13 14export async function exportEmbedAsync(projectRoot: string, options: Options) { 15 setNodeEnv(options.dev ? 'development' : 'production'); 16 require('@expo/env').load(projectRoot); 17 18 const { config } = await loadMetroConfigAsync( 19 projectRoot, 20 { 21 maxWorkers: options.maxWorkers, 22 resetCache: options.resetCache, 23 config: options.config, 24 }, 25 { 26 isExporting: true, 27 } 28 ); 29 30 // NOTE(EvanBacon): This may need to be adjusted in the future if want to support basePath on native 31 // platforms when doing production embeds (unlikely). 32 const saveAssets = importCliSaveAssetsFromProject(projectRoot); 33 34 let sourceMapUrl = options.sourcemapOutput; 35 if (sourceMapUrl && !options.sourcemapUseAbsolutePath) { 36 sourceMapUrl = path.basename(sourceMapUrl); 37 } 38 39 const bundleRequest = { 40 ...Server.DEFAULT_BUNDLE_OPTIONS, 41 entryFile: options.entryFile, 42 sourceMapUrl, 43 dev: options.dev, 44 minify: !!options.minify, 45 platform: options.platform, 46 unstable_transformProfile: 47 options.unstableTransformProfile as BundleOptions['unstable_transformProfile'], 48 }; 49 50 const server = new Server(config, { 51 watch: false, 52 }); 53 54 try { 55 const bundle = await server.build({ 56 ...bundleRequest, 57 bundleType: 'bundle', 58 }); 59 60 fs.mkdirSync(path.dirname(options.bundleOutput), { recursive: true, mode: 0o755 }); 61 62 // Persist bundle and source maps. 63 await output.save(bundle, options, Log.log); 64 65 // Save the assets of the bundle 66 const outputAssets = await getAssets(server, { 67 ...bundleRequest, 68 bundleType: 'todo', 69 }); 70 71 await saveAssets(outputAssets, options.platform, options.assetsDest, options.assetCatalogDest); 72 } finally { 73 server.end(); 74 } 75} 76