Skip to content

Instantly share code, notes, and snippets.

@janicduplessis
Last active May 14, 2019 09:17
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save janicduplessis/30ec95451733d34ffcf7d5cb27ba0e28 to your computer and use it in GitHub Desktop.
Save janicduplessis/30ec95451733d34ffcf7d5cb27ba0e28 to your computer and use it in GitHub Desktop.
// Gradle script for detached apps.
import org.apache.tools.ant.taskdefs.condition.Os
void runBefore(String dependentTaskName, Task task) {
Task dependentTask = tasks.findByPath(dependentTaskName);
if (dependentTask != null) {
dependentTask.dependsOn task
}
}
afterEvaluate {
def expoRoot = file("../../")
def inputExcludes = ["android/**", "ios/**"]
task exponentPrebuildStep(type: Exec) {
workingDir expoRoot
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine "cmd", "/c", ".\\android\\detach-scripts\\run-exp.bat"
} else {
commandLine "./android/detach-scripts/run-exp.sh", "prepare-detached-build", "--platform", "android", expoRoot
}
}
runBefore("preBuild", exponentPrebuildStep)
// Based on https://github.com/facebook/react-native/blob/master/react.gradle
// Grab all build types and product flavors
def buildTypes = android.buildTypes.collect { type -> type.name }
def productFlavors = android.productFlavors.collect { flavor -> flavor.name }
// When no product flavors defined, use empty
if (!productFlavors) productFlavors.add("")
productFlavors.each { productFlavorName ->
buildTypes.each { buildTypeName ->
// Create variant and target names
def flavorNameCapitalized = "${productFlavorName.capitalize()}"
def buildNameCapitalized = "${buildTypeName.capitalize()}"
def targetName = "${flavorNameCapitalized}${buildNameCapitalized}"
def targetPath = productFlavorName ?
"${productFlavorName}/${buildTypeName}" :
"${buildTypeName}"
def assetsDir = file("$buildDir/intermediates/assets/${targetPath}")
// Bundle task name for variant
def bundleExpoAssetsTaskName = "bundle${targetName}ExpoAssets"
def currentBundleTask = tasks.create(
name: bundleExpoAssetsTaskName,
type: Exec) {
description = "Expo bundle assets for ${targetName}."
// Create dirs if they are not there (e.g. the "clean" task just ran)
doFirst {
assetsDir.mkdirs()
}
// Set up inputs and outputs so gradle can cache the result
inputs.files fileTree(dir: expoRoot, excludes: inputExcludes)
outputs.dir assetsDir
// Set up the call to exp
workingDir expoRoot
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine("cmd", "/c", ".\\android\\detach-scripts\\run-exp.bat", "bundle-assets", expoRoot, "--platform", "android", "--dest", assetsDir)
} else {
commandLine("./android/detach-scripts/run-exp.sh", "bundle-assets", expoRoot, "--platform", "android", "--dest", assetsDir)
}
enabled targetName.toLowerCase().contains("release") || targetName.toLowerCase().contains("prod")
}
currentBundleTask.dependsOn("merge${targetName}Resources")
currentBundleTask.dependsOn("merge${targetName}Assets")
runBefore("process${targetName}Resources", currentBundleTask)
}
}
}

Manual standalone app update to Expo SDK 27

Make sure to update exp!

Add assetBundlePatterns to your manifest with paths to your assets folder or just the **/* wildcard:

"assetBundlePatterns": [
  "**/*"
],

iOS

In xcode, go to your project settings, build phases and create a new run script phase called Bundle Expo Assets with this as the script:

set -eo pipefail

if [ "$CONFIGURATION" == "Debug" ]; then
  echo "Skipping asset bundling in debug mode."
  exit 0
fi

pushd ${SRCROOT}/..
value=$(cat ~/.expo/PATH)
dest=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH
PATH="$PATH:$value" exp bundle-assets --platform ios --dest "$dest"
popd

Make sure your manifest contains the following keys:

  • ios.publishBundlePath: "ios/<your_app_slug>/Supporting/shell-app.bundle"
  • ios.publishManifestPath: "ios/<your_app_slug>/Supporting/shell-app-manifest.json"

Android

Copy the following files:

  • run-exp.bat and run-exp.sh to the android/detach-scripts folder, you may also delete the other files in this directory.
  • expo.gradle to the android/app folder.

You may need to grant execute permissions to run-exp.sh on unix systems (chmod +x android/detach-scripts/run-exp.sh).

In android/app/build.gradle remove the exponentPrebuildStep method and add apply from: 'expo.gradle'.

-task exponentPrebuildStep(type: Exec) {
-  workingDir '../'
-  if (System.getProperty('os.name').toLowerCase().contains('windows')) {
-    commandLine 'cmd', '/c', '.\\detach-scripts\\prepare-detached-build.bat'
-  } else {
-    commandLine './detach-scripts/prepare-detached-build.sh'
-  }
-}
-preBuild.dependsOn exponentPrebuildStep
+apply from: 'expo.gradle'

Add the following keys to your manifest:

  • android.publishBundlePath: "android/app/src/main/assets/shell-app.bundle"
  • android.publishManifestPath: "android/app/src/main/assets/shell-app-manifest.json"

Make sure to publish a new version first and then production builds will work offline!

SET /P STOREDPATH=<"%USERPROFILE%\.expo\PATH"
SET PATH="\"%PATH%;%STOREDPATH%\""
exp %*
#!/bin/bash
value=$(cat ~/.expo/PATH)
PATH="$PATH:$value" exp "$@"
@iuliuvisovan
Copy link

I think this is a bit unclear. What exactly is "my manifest"?

@dasblitz
Copy link

@iuliuvisovan I think they mean app.json in the root of your project

@arnoldbird
Copy link

Elsewhere, there are indications that the manifest is not the same thing as app.json. So I'm with @iuliuvisovan on this -- I don't see what or where the manifest is. I posted a question to the forum: https://forums.expo.io/t/what-where-is-the-manifest/11870

@amanforindia
Copy link

For iOS, also remember to create the file references of shell-app.bundle and shell-app-manifest.json in Xcode otherwise it won't package these files in the binary and offline support won't work. I got stuck over this for a couple of days :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment