Skip to content

Instantly share code, notes, and snippets.

@EvanBacon
Created August 20, 2021 20:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EvanBacon/3376bdccb30ab9e6592c8d43c0c84049 to your computer and use it in GitHub Desktop.
Save EvanBacon/3376bdccb30ab9e6592c8d43c0c84049 to your computer and use it in GitHub Desktop.
Emulate "public path" functionality in React Native
import { Platform } from "react-native";
import getDevServer from "react-native/Libraries/Core/Devtools/getDevServer";
const devServerInfo = getDevServer();
/**
* Transform a local "public" path location to a URL that works in React Native.
*
* When the project is not hosted from a development server, use an offline path from an embedded asset.
*
* ```js
* transformAssetLocation('node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/chevron-left.png')
* ```
*
* ```jsx
* <Image style={{ width: 100, height: 100 }} source={{ uri: transformAssetLocation('node_modules/react-native/Libraries/LogBox/UI/LogBoxImages/chevron-left.png') }} />
* ```
*
* Alternatively a project hosted from something like EAS Updates can use the hosted path + public path to retrieve assets.
*
* @param assetPath
* @returns
*/
export function transformAssetLocation(assetPath: string) {
// Dev server in use
if (devServerInfo.bundleLoadedFromServer) {
// Remote
const url = !devServerInfo.url.endsWith("/")
? `${devServerInfo.url}/`
: devServerInfo.url;
return url + assetPath;
} else {
// Local files bundled in the Android binary
if (Platform.OS === "android") {
// Use the same asset resolution code as the `expo bundle` command
const normalized = getAndroidResourceIdentifier(assetPath);
// Return a URL for a file in the assets folder.
return `asset:/${normalized}`;
} else if (Platform.OS === "ios") {
// Not sure what the recommended way to retrieve embedded iOS assets is??
// Maybe some combo of https://github.com/react-native-community/cli/pull/1290 and
// https://reactnative.dev/docs/images#images-from-hybrid-apps-resources
throw Error("no imp ios production");
}
}
}
function getAndroidResourceIdentifier(asset): string {
return `${asset}`
.toLowerCase()
.replace(/\//g, "_") // Encode folder structure in file name
.replace(/([^a-z0-9_])/g, "") // Remove illegal chars
.replace(/^assets_/, ""); // Remove "assets_" prefix
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment