UNPKG

@expo/metro-config

Version:

A Metro config for running React Native projects with the Metro bundler

113 lines 4.58 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildHermesBundleAsync = void 0; const spawn_async_1 = __importDefault(require("@expo/spawn-async")); const chalk_1 = __importDefault(require("chalk")); const fs_extra_1 = __importDefault(require("fs-extra")); const metro_source_map_1 = require("metro-source-map"); const os_1 = __importDefault(require("os")); const path_1 = __importDefault(require("path")); const process_1 = __importDefault(require("process")); const debug = require('debug')('expo:metro:hermes'); function importHermesCommandFromProject() { const platformExecutable = getHermesCommandPlatform(); const hermescLocations = [ // Override hermesc dir by environment variables process_1.default.env['REACT_NATIVE_OVERRIDE_HERMES_DIR'] ? `${process_1.default.env['REACT_NATIVE_OVERRIDE_HERMES_DIR']}/build/bin/hermesc` : '', // Building hermes from source 'react-native/ReactAndroid/hermes-engine/build/hermes/bin/hermesc', // Prebuilt hermesc in official react-native 0.69+ `react-native/sdks/hermesc/${platformExecutable}`, // Legacy hermes-engine package `hermes-engine/${platformExecutable}`, ]; for (const location of hermescLocations) { try { return require.resolve(location); } catch { } } throw new Error('Cannot find the hermesc executable.'); } function getHermesCommandPlatform() { switch (os_1.default.platform()) { case 'darwin': return 'osx-bin/hermesc'; case 'linux': return 'linux64-bin/hermesc'; case 'win32': return 'win64-bin/hermesc.exe'; default: throw new Error(`Unsupported host platform for Hermes compiler: ${os_1.default.platform()}`); } } // Only one hermes build at a time is supported. let currentHermesBuild = null; async function buildHermesBundleAsync(options) { if (currentHermesBuild) { debug(`Waiting for existing Hermes builds to finish`); await currentHermesBuild; } currentHermesBuild = directlyBuildHermesBundleAsync(options); return await currentHermesBuild; } exports.buildHermesBundleAsync = buildHermesBundleAsync; async function directlyBuildHermesBundleAsync({ code, map, minify = false, filename, }) { const tempDir = path_1.default.join(os_1.default.tmpdir(), `expo-bundler-${Math.random()}-${Date.now()}`); await fs_extra_1.default.ensureDir(tempDir); try { const tempBundleFile = path_1.default.join(tempDir, 'index.js'); await fs_extra_1.default.writeFile(tempBundleFile, code); if (map) { const tempSourcemapFile = path_1.default.join(tempDir, 'index.js.map'); await fs_extra_1.default.writeFile(tempSourcemapFile, map); } const tempHbcFile = path_1.default.join(tempDir, 'index.hbc'); const hermesCommand = importHermesCommandFromProject(); const args = ['-emit-binary', '-out', tempHbcFile, tempBundleFile]; if (minify) { args.push('-O'); } if (map) { args.push('-output-source-map'); } debug(`Running hermesc: ${hermesCommand} ${args.join(' ')}`); await (0, spawn_async_1.default)(hermesCommand, args); let hbc; let sourcemap = null; if (!map) { hbc = await fs_extra_1.default.readFile(tempHbcFile); } else { [hbc, sourcemap] = await Promise.all([ fs_extra_1.default.readFile(tempHbcFile), createHermesSourcemapAsync(map, `${tempHbcFile}.map`), ]); } return { hbc, sourcemap, }; } catch (error) { console.error(chalk_1.default.red(`\nFailed to generate Hermes bytecode for: ${filename}`)); if ('status' in error) { console.error(error.output.join('\n')); } throw error; } finally { await fs_extra_1.default.remove(tempDir); } } async function createHermesSourcemapAsync(sourcemap, hermesMapFile) { const bundlerSourcemap = JSON.parse(sourcemap); const hermesSourcemap = await fs_extra_1.default.readJSON(hermesMapFile); return JSON.stringify((0, metro_source_map_1.composeSourceMaps)([bundlerSourcemap, hermesSourcemap])); } //# sourceMappingURL=exportHermes.js.map