GT2/Ejectable/node_modules/@expo/metro-config/build/ExpoMetroConfig.js

201 lines
9.8 KiB
JavaScript
Raw Normal View History

2021-08-16 00:14:59 +00:00
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadAsync = exports.getDefaultConfig = exports.INTERNAL_CALLSITES_REGEX = exports.EXPO_DEBUG = void 0;
const config_1 = require("@expo/config");
const paths_1 = require("@expo/config/paths");
const chalk_1 = __importDefault(require("chalk"));
const getenv_1 = require("getenv");
const path_1 = __importDefault(require("path"));
const resolve_from_1 = __importDefault(require("resolve-from"));
exports.EXPO_DEBUG = getenv_1.boolish('EXPO_DEBUG', false);
// Import only the types here, the values will be imported from the project, at runtime.
exports.INTERNAL_CALLSITES_REGEX = new RegExp([
'/Libraries/Renderer/implementations/.+\\.js$',
'/Libraries/BatchedBridge/MessageQueue\\.js$',
'/Libraries/YellowBox/.+\\.js$',
'/Libraries/LogBox/.+\\.js$',
'/Libraries/Core/Timers/.+\\.js$',
'node_modules/react-devtools-core/.+\\.js$',
'node_modules/react-refresh/.+\\.js$',
'node_modules/scheduler/.+\\.js$',
// Metro replaces `require()` with a different method,
// we want to omit this method from the stack trace.
// This is akin to most React tooling.
'/metro/.*/polyfills/require.js$',
// Hide frames related to a fast refresh.
'/metro/.*/lib/bundle-modules/.+\\.js$',
'/metro/.*/lib/bundle-modules/.+\\.js$',
'node_modules/react-native/Libraries/Utilities/HMRClient.js$',
'node_modules/eventemitter3/index.js',
'node_modules/event-target-shim/dist/.+\\.js$',
// Ignore the log forwarder used in the Expo Go app
'/expo/build/environment/react-native-logs.fx.js$',
'/expo/build/logs/RemoteConsole.js$',
// Improve errors thrown by invariant (ex: `Invariant Violation: "main" has not been registered`).
'node_modules/invariant/.+\\.js$',
// Remove babel runtime additions
'node_modules/regenerator-runtime/.+\\.js$',
// Remove react native setImmediate ponyfill
'node_modules/promise/setimmediate/.+\\.js$',
// Babel helpers that implement language features
'node_modules/@babel/runtime/.+\\.js$',
// Block native code invocations
`\\[native code\\]`,
].join('|'));
function readIsLegacyImportsEnabled(projectRoot) {
const config = config_1.getConfig(projectRoot, { skipSDKVersionRequirement: true });
return config_1.isLegacyImportsEnabled(config.exp);
}
function getProjectBabelConfigFile(projectRoot) {
return (resolve_from_1.default.silent(projectRoot, './babel.config.js') ||
resolve_from_1.default.silent(projectRoot, './.babelrc') ||
resolve_from_1.default.silent(projectRoot, './.babelrc.js'));
}
function getDefaultConfig(projectRoot, options = {}) {
const MetroConfig = importMetroConfigFromProject(projectRoot);
const reactNativePath = path_1.default.dirname(resolve_from_1.default(projectRoot, 'react-native/package.json'));
try {
// Set the `EXPO_METRO_CACHE_KEY_VERSION` variable for use in the custom babel transformer.
// This hack is used because there doesn't appear to be anyway to resolve
// `babel-preset-fbjs` relative to the project root later (in `metro-expo-babel-transformer`).
const babelPresetFbjsPath = resolve_from_1.default(projectRoot, 'babel-preset-fbjs/package.json');
process.env.EXPO_METRO_CACHE_KEY_VERSION = String(require(babelPresetFbjsPath).version);
}
catch {
// noop -- falls back to a hardcoded value.
}
let hashAssetFilesPath;
try {
hashAssetFilesPath = resolve_from_1.default(projectRoot, 'expo-asset/tools/hashAssetFiles');
}
catch {
// TODO: we should warn/throw an error if the user has expo-updates installed but does not
// have hashAssetFiles available, or if the user is in managed workflow and does not have
// hashAssetFiles available. but in a bare app w/o expo-updates, just using dev-client,
// it is not needed
}
const isLegacy = readIsLegacyImportsEnabled(projectRoot);
// Deprecated -- SDK 41 --
if (options.target) {
if (!isLegacy) {
console.warn(chalk_1.default.yellow(`The target option is deprecated. Learn more: http://expo.fyi/expo-extension-migration`));
delete options.target;
}
}
else if (process.env.EXPO_TARGET) {
console.error('EXPO_TARGET is deprecated. Learn more: http://expo.fyi/expo-extension-migration');
if (isLegacy) {
// EXPO_TARGET is used by @expo/metro-config to determine the target when getDefaultConfig is
// called from metro.config.js.
// @ts-ignore
options.target = process.env.EXPO_TARGET;
}
}
else if (isLegacy) {
// Fall back to guessing based on the project structure in legacy mode.
options.target = config_1.getDefaultTarget(projectRoot);
}
if (!options.target) {
// Default to bare -- no .expo extension.
options.target = 'bare';
}
// End deprecated -- SDK 41 --
const { target } = options;
if (!(target === 'managed' || target === 'bare')) {
throw new Error(`Invalid target: '${target}'. Debug info: \n${JSON.stringify({
'options.target': options.target,
default: config_1.getDefaultTarget(projectRoot),
}, null, 2)}`);
}
const sourceExtsConfig = { isTS: true, isReact: true, isModern: false };
const sourceExts = target === 'bare'
? paths_1.getBareExtensions([], sourceExtsConfig)
: paths_1.getManagedExtensions([], sourceExtsConfig);
const babelConfigPath = getProjectBabelConfigFile(projectRoot);
const isCustomBabelConfigDefined = !!babelConfigPath;
if (exports.EXPO_DEBUG) {
console.log();
console.log(`Expo Metro config:`);
console.log(`- Bundler target: ${target}`);
console.log(`- Legacy: ${isLegacy}`);
console.log(`- Extensions: ${sourceExts.join(', ')}`);
console.log(`- React Native: ${reactNativePath}`);
console.log(`- Babel config: ${babelConfigPath || 'babel-preset-expo (default)'}`);
console.log();
}
const {
// Remove the default reporter which metro always resolves to be the react-native-community/cli reporter.
// This prints a giant React logo which is less accessible to users on smaller terminals.
reporter, ...metroDefaultValues } = MetroConfig.getDefaultConfig.getDefaultValues(projectRoot);
// Merge in the default config from Metro here, even though loadConfig uses it as defaults.
// This is a convenience for getDefaultConfig use in metro.config.js, e.g. to modify assetExts.
return MetroConfig.mergeConfig(metroDefaultValues, {
resolver: {
resolverMainFields: ['react-native', 'browser', 'main'],
platforms: ['ios', 'android', 'native'],
sourceExts,
},
serializer: {
getModulesRunBeforeMainModule: () => [
require.resolve(path_1.default.join(reactNativePath, 'Libraries/Core/InitializeCore')),
// TODO: Bacon: load Expo side-effects
],
getPolyfills: () => require(path_1.default.join(reactNativePath, 'rn-get-polyfills'))(),
},
server: {
port: Number(process.env.RCT_METRO_PORT) || 8081,
},
symbolicator: {
customizeFrame: frame => {
var _a;
let collapse = Boolean(frame.file && exports.INTERNAL_CALLSITES_REGEX.test(frame.file));
if (!collapse) {
// This represents the first frame of the stacktrace.
// Often this looks like: `__r(0);`.
// The URL will also be unactionable in the app and therefore not very useful to the developer.
if (frame.column === 3 &&
frame.methodName === 'global code' &&
((_a = frame.file) === null || _a === void 0 ? void 0 : _a.match(/^https?:\/\//g))) {
collapse = true;
}
}
return { ...(frame || {}), collapse };
},
},
transformer: {
allowOptionalDependencies: true,
babelTransformerPath: isCustomBabelConfigDefined
? // If the user defined a babel config file in their project,
// then use the default transformer.
require.resolve('metro-react-native-babel-transformer')
: // Otherwise, use a custom transformer that uses `babel-preset-expo` by default for projects.
require.resolve('./metro-expo-babel-transformer'),
assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
assetPlugins: hashAssetFilesPath ? [hashAssetFilesPath] : undefined,
},
});
}
exports.getDefaultConfig = getDefaultConfig;
async function loadAsync(projectRoot, { reporter, target, ...metroOptions } = {}) {
let defaultConfig = getDefaultConfig(projectRoot, { target });
if (reporter) {
defaultConfig = { ...defaultConfig, reporter };
}
const MetroConfig = importMetroConfigFromProject(projectRoot);
return await MetroConfig.loadConfig({ cwd: projectRoot, projectRoot, ...metroOptions }, defaultConfig);
}
exports.loadAsync = loadAsync;
function importMetroConfigFromProject(projectRoot) {
const resolvedPath = resolve_from_1.default.silent(projectRoot, 'metro-config');
if (!resolvedPath) {
throw new Error('Missing package "metro-config" in the project. ' +
'This usually means `react-native` is not installed. ' +
'Please verify that dependencies in package.json include "react-native" ' +
'and run `yarn` or `npm install`.');
}
return require(resolvedPath);
}
//# sourceMappingURL=ExpoMetroConfig.js.map