1dc51e206SEvan Baconimport { Platform } from '@expo/config';
2dc51e206SEvan Baconimport chalk from 'chalk';
3dc51e206SEvan Baconimport prettyBytes from 'pretty-bytes';
4dc51e206SEvan Baconimport table from 'text-table';
5dc51e206SEvan Bacon
6*8a424bebSJames Ideimport { BundleOutput } from './fork-bundleAsync';
7dc51e206SEvan Baconimport * as Log from '../log';
8dc51e206SEvan Baconimport { stripAnsi } from '../utils/ansi';
9dc51e206SEvan Baconimport { learnMore } from '../utils/link';
10dc51e206SEvan Bacon
11dc51e206SEvan Baconexport function printBundleSizes(bundles: Partial<Record<Platform, BundleOutput>>) {
12dc51e206SEvan Bacon  const files: [string, string | Uint8Array][] = [];
13dc51e206SEvan Bacon
142beab412SEvan Bacon  for (const [platform, bundleOutput] of Object.entries(bundles) as [
152beab412SEvan Bacon    Platform,
16*8a424bebSJames Ide    Pick<BundleOutput, 'hermesBytecodeBundle' | 'code' | 'hermesSourcemap' | 'map'>,
172beab412SEvan Bacon  ][]) {
182beab412SEvan Bacon    if (bundleOutput.hermesBytecodeBundle) {
19864ec879SEvan Bacon      files.push([chalk.bold(`index.${platform}.hbc`), bundleOutput.hermesBytecodeBundle]);
202beab412SEvan Bacon    } else if (bundleOutput.code) {
212beab412SEvan Bacon      files.push([chalk.bold(`index.${platform}.js`), bundleOutput.code]);
22dc51e206SEvan Bacon    }
232beab412SEvan Bacon    if (bundleOutput.hermesSourcemap) {
24864ec879SEvan Bacon      files.push([chalk.dim(`index.${platform}.hbc.map`), bundleOutput.hermesSourcemap]);
252beab412SEvan Bacon    } else if (bundleOutput.map) {
262beab412SEvan Bacon      files.push([chalk.dim(`index.${platform}.js.map`), bundleOutput.map]);
27dc51e206SEvan Bacon    }
28dc51e206SEvan Bacon  }
29dc51e206SEvan Bacon
30dc51e206SEvan Bacon  Log.log();
312beab412SEvan Bacon  Log.log(createFilesTable(files.sort((a, b) => a[1].length - b[1].length)));
32dc51e206SEvan Bacon  Log.log();
33dc51e206SEvan Bacon  Log.log(
34dc51e206SEvan Bacon    chalk`�� JavaScript bundle sizes affect startup time. {dim ${learnMore(
35dc51e206SEvan Bacon      `https://expo.fyi/javascript-bundle-sizes`
36dc51e206SEvan Bacon    )}}`
37dc51e206SEvan Bacon  );
38dc51e206SEvan Bacon  Log.log();
39dc51e206SEvan Bacon
40dc51e206SEvan Bacon  return files;
41dc51e206SEvan Bacon}
42dc51e206SEvan Bacon
43dc51e206SEvan Baconexport function createFilesTable(files: [string, string | Uint8Array][]): string {
44dc51e206SEvan Bacon  const tableData = files.map((item, index) => {
45e330c216SEvan Bacon    const fileBranch =
46e330c216SEvan Bacon      index === 0 ? (files.length > 1 ? '┌' : '─') : index === files.length - 1 ? '└' : '├';
47dc51e206SEvan Bacon
48dc51e206SEvan Bacon    return [`${fileBranch} ${item[0]}`, prettyBytes(Buffer.byteLength(item[1], 'utf8'))];
49dc51e206SEvan Bacon  });
50dc51e206SEvan Bacon  return table([['Bundle', 'Size'].map((v) => chalk.underline(v)), ...tableData], {
51dc51e206SEvan Bacon    align: ['l', 'r'],
52dc51e206SEvan Bacon    stringLength: (str) => stripAnsi(str)?.length ?? 0,
53dc51e206SEvan Bacon  });
54dc51e206SEvan Bacon}
55