Skip to content

Commit d51b5ad

Browse files
committed
iOS: avoid full xcodebuild on scenario switches
Each scenario switch within a test suite re-ran a complete xcodebuild of the test app, even though the native code and Podfile never change between scenarios - only the JS bundle does. This made every single test pay for a full native rebuild. Perform the real xcodebuild only once per project; subsequent calls just re-run react-native-xcode.sh (the same script Xcode's own "Bundle React Native code and images" build phase invokes) to re-package the JS bundle and assets directly into the already-built .app.
1 parent 707635d commit d51b5ad

1 file changed

Lines changed: 51 additions & 2 deletions

File tree

test/test.ts

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,58 @@ class RNIOS extends Platform.IOS implements RNPlatform {
276276
private static iosFirstBuild: any = {};
277277

278278
/**
279-
* Builds the binary of the project on this platform.
279+
* Maps project directories to whether or not a real `xcodebuild` has completed for them yet.
280+
* Once true, subsequent scenario switches only need their JS bundle re-packaged, not a full
281+
* native rebuild, since the native code/Podfile don't change between scenarios.
282+
*/
283+
private static hasBuiltOnce: { [projectDirectory: string]: boolean } = {};
284+
285+
/**
286+
* Builds the binary of the project on this platform. Only performs a real `xcodebuild` the
287+
* first time; subsequent calls for the same project just re-bundle the JS (see `bundleOnly`).
280288
*/
281289
buildApp(projectDirectory: string): Q.Promise<void> {
290+
if (RNIOS.hasBuiltOnce[projectDirectory]) {
291+
return this.bundleOnly(projectDirectory);
292+
}
293+
return this.realBuildApp(projectDirectory)
294+
.then(() => { RNIOS.hasBuiltOnce[projectDirectory] = true; });
295+
}
296+
297+
/**
298+
* Re-packages the JS bundle (and copies assets) into the already-built `.app`, by invoking
299+
* `react-native-xcode.sh` directly instead of going through a full `xcodebuild`. This is the
300+
* same script Xcode's "Bundle React Native code and images" build phase runs; the native code
301+
* doesn't change between scenarios, so re-running the whole build graph is unnecessary.
302+
*/
303+
private bundleOnly(projectDirectory: string): Q.Promise<void> {
304+
const iOSProject: string = path.join(projectDirectory, TestConfig.TestAppName, "ios");
305+
const configurationBuildDir = path.dirname(this.getBinaryPath(projectDirectory));
306+
const wrapperName = `${TestConfig.TestAppName}.app`;
307+
const scriptPath = path.join(projectDirectory, TestConfig.TestAppName, "node_modules", "react-native", "scripts", "react-native-xcode.sh");
308+
309+
const env = Object.assign({}, process.env, {
310+
CONFIGURATION: "Release",
311+
PLATFORM_NAME: "iphonesimulator",
312+
CONFIGURATION_BUILD_DIR: configurationBuildDir,
313+
TARGET_BUILD_DIR: configurationBuildDir,
314+
BUILT_PRODUCTS_DIR: configurationBuildDir,
315+
UNLOCALIZED_RESOURCES_FOLDER_PATH: wrapperName,
316+
WRAPPER_NAME: wrapperName,
317+
PROJECT_DIR: iOSProject,
318+
SRCROOT: iOSProject,
319+
SOURCE_ROOT: iOSProject,
320+
PODS_ROOT: path.join(iOSProject, "Pods"),
321+
});
322+
323+
return TestUtil.getProcessOutput(`"${scriptPath}"`, { cwd: iOSProject, env, timeout: 2 * 60 * 1000, noLogStdOut: true, noLogStdErr: true })
324+
.then(() => { return null; });
325+
}
326+
327+
/**
328+
* Performs a full `xcodebuild` of the project on this platform.
329+
*/
330+
private realBuildApp(projectDirectory: string): Q.Promise<void> {
282331
const iOSProject: string = path.join(projectDirectory, TestConfig.TestAppName, "ios");
283332

284333
return this.getEmulatorManager().getTargetEmulator()
@@ -298,7 +347,7 @@ class RNIOS extends Platform.IOS implements RNPlatform {
298347
del.sync([iosBuildFolder], { force: true });
299348
}
300349
RNIOS.iosFirstBuild[projectDirectory] = true;
301-
return this.buildApp(projectDirectory);
350+
return this.realBuildApp(projectDirectory);
302351
}
303352
return null;
304353
});

0 commit comments

Comments
 (0)