1import path from 'path'; 2 3import * as Log from '../log'; 4import { ensureDirectoryAsync } from '../utils/dir'; 5import { createBundlesAsync } from './createBundles'; 6import { exportAssetsAsync } from './exportAssets'; 7import { getPublicExpoManifestAsync } from './getPublicExpoManifest'; 8import { printBundleSizes } from './printBundleSizes'; 9import { Options } from './resolveOptions'; 10import { 11 writeAssetMapAsync, 12 writeBundlesAsync, 13 writeDebugHtmlAsync, 14 writeMetadataJsonAsync, 15 writeSourceMapsAsync, 16} from './writeContents'; 17 18/** 19 * The structure of the outputDir will be: 20 * 21 * ``` 22 * ├── assets 23 * │ └── * 24 * ├── bundles 25 * │ ├── android-01ee6e3ab3e8c16a4d926c91808d5320.js 26 * │ └── ios-ee8206cc754d3f7aa9123b7f909d94ea.js 27 * └── metadata.json 28 * ``` 29 */ 30export async function exportAppAsync( 31 projectRoot: string, 32 { 33 platforms, 34 outputDir, 35 clear, 36 dev, 37 dumpAssetmap, 38 dumpSourcemap, 39 }: Pick<Options, 'dumpAssetmap' | 'dumpSourcemap' | 'dev' | 'clear' | 'outputDir' | 'platforms'> 40): Promise<void> { 41 const exp = await getPublicExpoManifestAsync(projectRoot); 42 43 const outputPath = path.resolve(projectRoot, outputDir); 44 const assetsPath = path.join(outputPath, 'assets'); 45 const bundlesPath = path.join(outputPath, 'bundles'); 46 47 await Promise.all([assetsPath, bundlesPath].map(ensureDirectoryAsync)); 48 49 // Run metro bundler and create the JS bundles/source maps. 50 const bundles = await createBundlesAsync( 51 projectRoot, 52 { resetCache: !!clear }, 53 { 54 platforms, 55 dev, 56 useDevServer: true, 57 // TODO: Disable source map generation if we aren't outputting them. 58 } 59 ); 60 61 // Log bundle size info to the user 62 printBundleSizes(bundles); 63 64 // Write the JS bundles to disk, and get the bundle file names (this could change with async chunk loading support). 65 const { hashes, fileNames } = await writeBundlesAsync({ bundles, outputDir: bundlesPath }); 66 67 Log.log('Finished saving JS Bundles'); 68 69 const { assets } = await exportAssetsAsync(projectRoot, { 70 exp, 71 outputDir: outputPath, 72 bundles, 73 }); 74 75 if (dumpAssetmap) { 76 Log.log('Dumping asset map'); 77 await writeAssetMapAsync({ outputDir: outputPath, assets }); 78 } 79 80 // build source maps 81 if (dumpSourcemap) { 82 Log.log('Dumping source maps'); 83 await writeSourceMapsAsync({ 84 bundles, 85 hashes, 86 outputDir: bundlesPath, 87 fileNames, 88 }); 89 90 Log.log('Preparing additional debugging files'); 91 // If we output source maps, then add a debug HTML file which the user can open in 92 // the web browser to inspect the output like web. 93 await writeDebugHtmlAsync({ 94 outputDir: outputPath, 95 fileNames, 96 }); 97 } 98 99 // Generate a `metadata.json` and the export is complete. 100 await writeMetadataJsonAsync({ outputDir, bundles, fileNames }); 101} 102