UNPKG

@expo/metro-runtime

Version:

Tools for making advanced Metro bundler features work

96 lines (80 loc) 2.87 kB
// This MUST be first to ensure that `fetch` is defined in the React Native environment. import 'react-native/Libraries/Core/InitializeCore'; // Ensure fetch is installed before adding our fetch polyfill to ensure Headers and Request are available globally. import 'whatwg-fetch'; // This MUST be imported to ensure URL is installed. import 'expo'; // This file configures the runtime environment to increase compatibility with WinterCG. // https://wintercg.org/ import Constants from 'expo-constants'; import { install, setLocationHref } from './Location'; import getDevServer from '../getDevServer'; interface ExpoExtraRouterConfig { router?: { origin?: any; generatedOrigin?: any; }; } const manifest = Constants.expoConfig; function getOrigin() { if (process.env.NODE_ENV !== 'production') { // e.g. http://localhost:8081 return getDevServer().url; } const extra = manifest?.extra as ExpoExtraRouterConfig | null; return ( extra?.router?.origin ?? // Written automatically during release builds. extra?.router?.generatedOrigin ); } // TODO: This would be better if native and tied as close to the JS engine as possible, i.e. it should // reflect the exact location of the JS file that was executed. function getBaseUrl() { // TODO: Make it official by moving out of `extra` const productionBaseUrl = getOrigin(); if (!productionBaseUrl) { return null; } // Ensure no trailing slash return productionBaseUrl?.replace(/\/$/, ''); } const polyfillSymbol = Symbol.for('expo.polyfillFetchWithWindowLocation'); export function wrapFetchWithWindowLocation(fetch: Function & { [polyfillSymbol]?: boolean }) { if (fetch[polyfillSymbol]) { return fetch; } const _fetch = (...props: any[]) => { if (props[0] && typeof props[0] === 'string' && props[0].startsWith('/')) { props[0] = new URL(props[0], window.location?.origin).toString(); } else if (props[0] && typeof props[0] === 'object') { if (props[0].url && typeof props[0].url === 'string' && props[0].url.startsWith('/')) { props[0].url = new URL(props[0].url, window.location?.origin).toString(); } } return fetch(...props); }; _fetch[polyfillSymbol] = true; return _fetch; } const extra = manifest?.extra as ExpoExtraRouterConfig | null; if (extra?.router?.origin !== false) { // Polyfill window.location in native runtimes. if (typeof window !== 'undefined' && !window.location) { const url = getBaseUrl(); if (url) { setLocationHref(url); install(); } } // Polyfill native fetch to support relative URLs Object.defineProperty(global, 'fetch', { // value: fetch, value: wrapFetchWithWindowLocation(fetch), }); } else { // Polyfill native fetch to support relative URLs Object.defineProperty(global, 'fetch', { value: fetch, }); }