From ce72cd27814ab1c3c97948aea57512817ad119da Mon Sep 17 00:00:00 2001 From: Matt Chowning Date: Thu, 14 May 2020 12:43:34 -0400 Subject: [PATCH 1/4] Only rebuild JS bundle if inputs or bundle file has changed --- .../android/build.gradle | 59 +++++++++++++++---- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/react-native-gutenberg-bridge/android/build.gradle b/react-native-gutenberg-bridge/android/build.gradle index 033357aefa..551240df74 100644 --- a/react-native-gutenberg-bridge/android/build.gradle +++ b/react-native-gutenberg-bridge/android/build.gradle @@ -163,21 +163,53 @@ dependencies { releaseImplementation files(hermesPath + "hermes-release.aar") } +boolean isBundleUpToDate() { + return project.hasProperty('isBundleUpToDate') && isBundleUpToDate +} + if (buildGutenbergMobileJSBundle) { def assetsFolder = 'src/main/assets' - def aarFolder = 'src/main/assets' + def jsRootDir = '../..' + + task bundleUpToDateCheck { + description("Checks if the inputs to the javascript bundle and the bundle itself are unchanged. \ +Only if they are is the isBundleUpToDate flag set to true. That flag is used by other tasks.") + inputs.files("$jsRootDir/package.json", + "$jsRootDir/yarn.lock") + inputs.dir("$jsRootDir/patches") + outputs.file("$assetsFolder/index.android.bundle") + + // set flag to true before task tries to run + project.ext.isBundleUpToDate = true + doLast { + // If this task runs, either the inputs or outputs have changed, so the bundle is out of date. + project.ext.isBundleUpToDate = false + } + } + + yarn_install.dependsOn bundleUpToDateCheck + yarn_install.onlyIf { !isBundleUpToDate() } task buildJSBundle(type: YarnTask) { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + args = ['bundle:android'] } - task ensureAssetsDirectory { + task ensureAssetsDirectory { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + doLast { mkdir assetsFolder } } task backupHermesDebugAAR(type: Copy) { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + def origFileName = 'hermes-debug.aar' def origWithPath = hermesOriginalPath + origFileName from origWithPath @@ -188,6 +220,9 @@ if (buildGutenbergMobileJSBundle) { } task backupHermesReleaseAAR(type: Copy) { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + def origFileName = 'hermes-release.aar' def origWithPath = hermesOriginalPath + origFileName from origWithPath @@ -198,6 +233,9 @@ if (buildGutenbergMobileJSBundle) { } task copyJSBundle(type: Copy) { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + def origFileName = 'App.js' def origWithPath = "../../bundle/android/${origFileName}" def target = 'index.android.bundle' @@ -210,15 +248,16 @@ if (buildGutenbergMobileJSBundle) { } task cleanupNodeModulesFolder(type: Delete) { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + delete '../../node_modules' } - if (buildGutenbergMobileJSBundle) { - preBuild.dependsOn(cleanupNodeModulesFolder) - cleanupNodeModulesFolder.dependsOn(backupHermesDebugAAR) - backupHermesDebugAAR.dependsOn(backupHermesReleaseAAR) - backupHermesReleaseAAR.dependsOn(copyJSBundle) - copyJSBundle.dependsOn(buildJSBundle) - buildJSBundle.dependsOn(yarn_install, ensureAssetsDirectory) - } + preBuild.dependsOn(cleanupNodeModulesFolder) + cleanupNodeModulesFolder.dependsOn(backupHermesDebugAAR) + backupHermesDebugAAR.dependsOn(backupHermesReleaseAAR) + backupHermesReleaseAAR.dependsOn(copyJSBundle) + copyJSBundle.dependsOn(buildJSBundle) + buildJSBundle.dependsOn(yarn_install, ensureAssetsDirectory) } From ae6feff4d02ab8f7fa83d335ba09a1ec66f52cc5 Mon Sep 17 00:00:00 2001 From: Matt Chowning Date: Thu, 14 May 2020 22:04:23 -0400 Subject: [PATCH 2/4] Broaden js bundle inputs --- .../android/build.gradle | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/react-native-gutenberg-bridge/android/build.gradle b/react-native-gutenberg-bridge/android/build.gradle index 551240df74..84df9d2d20 100644 --- a/react-native-gutenberg-bridge/android/build.gradle +++ b/react-native-gutenberg-bridge/android/build.gradle @@ -174,9 +174,43 @@ if (buildGutenbergMobileJSBundle) { task bundleUpToDateCheck { description("Checks if the inputs to the javascript bundle and the bundle itself are unchanged. \ Only if they are is the isBundleUpToDate flag set to true. That flag is used by other tasks.") - inputs.files("$jsRootDir/package.json", - "$jsRootDir/yarn.lock") - inputs.dir("$jsRootDir/patches") + + def isRelevantFile = { it.name.endsWithAny('.js', '.css') || it.name == 'package.json' } + def inputFiles = { + def jsFiles = [] + def dirs = [] + file(jsRootDir).eachDir { dir -> + if (dir.name != 'node_modules' + && dir.name != 'bundle' + && dir.name != 'gutenberg' + && !dir.name.startsWith('symlinked')) { + dirs << dir + } + } + file("$jsRootDir/gutenberg").eachDir { dir -> + if (dir.name != 'node_modules') { + dirs << dir + } + } + + dirs.forEach { dir -> + file(dir).eachFileRecurse { + if (isRelevantFile(it)) { + jsFiles << it + } + } + } + + def jsRootDirFiles = file(jsRootDir).listFiles().findAll { + isRelevantFile(it) + } + def gutenbergRootDirFiles = file("$jsRootDir/gutenberg").listFiles().findAll { + isRelevantFile(it) + } + return jsFiles + jsRootDirFiles + gutenbergRootDirFiles + } + inputs.files(inputFiles()) + outputs.file("$assetsFolder/index.android.bundle") // set flag to true before task tries to run From ffc520aaea32a611e4315c4820cc7b5827a70231 Mon Sep 17 00:00:00 2001 From: Matt Chowning Date: Fri, 15 May 2020 12:21:00 -0400 Subject: [PATCH 3/4] Move bundle to build folder and improve incremental builds Now running `clean` will delete the current js bundle and the next build will know to generate a new one. --- .../android/build.gradle | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/react-native-gutenberg-bridge/android/build.gradle b/react-native-gutenberg-bridge/android/build.gradle index 84df9d2d20..80124ab096 100644 --- a/react-native-gutenberg-bridge/android/build.gradle +++ b/react-native-gutenberg-bridge/android/build.gradle @@ -91,6 +91,7 @@ project.ext.buildGutenbergFromSource = false def hermesOriginalPath = "../../node_modules/hermes-engine/android/"; def hermesPath = hermesOriginalPath; +def buildAssetsFolder = 'build/assets' android { compileSdkVersion 28 @@ -109,6 +110,12 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + sourceSets { + main { + assets.srcDirs += buildAssetsFolder + } + } } repositories { @@ -168,7 +175,7 @@ boolean isBundleUpToDate() { } if (buildGutenbergMobileJSBundle) { - def assetsFolder = 'src/main/assets' + def bundleName = 'index.android.bundle' def jsRootDir = '../..' task bundleUpToDateCheck { @@ -211,13 +218,24 @@ Only if they are is the isBundleUpToDate flag set to true. That flag is used by } inputs.files(inputFiles()) - outputs.file("$assetsFolder/index.android.bundle") + outputs.file("$buildAssetsFolder/$bundleName") + + // Having this task create this file as an output because changes to + // the actual bundle (or even deleting the bundle file) was not triggering + // this task to rerun (and flip the isBundleUpToDate flag to false). Now that + // this second indicator file is here, which gets deleted if the project is cleaned, + // this task knows that it is out of date. Note that if there are changes to the + // bundle file though, that alone will not trigger this task to run again, so you'll + // need to use --rerun-tasks in that case. + def upToDateIndicatorFile = "$buildAssetsFolder/up-to-date-bundle-indicator" + outputs.file(upToDateIndicatorFile) // set flag to true before task tries to run project.ext.isBundleUpToDate = true doLast { // If this task runs, either the inputs or outputs have changed, so the bundle is out of date. project.ext.isBundleUpToDate = false + file(upToDateIndicatorFile).createNewFile() } } @@ -231,15 +249,6 @@ Only if they are is the isBundleUpToDate flag set to true. That flag is used by args = ['bundle:android'] } - task ensureAssetsDirectory { - dependsOn bundleUpToDateCheck - onlyIf { !isBundleUpToDate() } - - doLast { - mkdir assetsFolder - } - } - task backupHermesDebugAAR(type: Copy) { dependsOn bundleUpToDateCheck onlyIf { !isBundleUpToDate() } @@ -272,10 +281,9 @@ Only if they are is the isBundleUpToDate flag set to true. That flag is used by def origFileName = 'App.js' def origWithPath = "../../bundle/android/${origFileName}" - def target = 'index.android.bundle' from origWithPath - into assetsFolder - rename origFileName, target + into buildAssetsFolder + rename origFileName, bundleName doLast { println "Done copying the Android JS bundle to assets folder" } @@ -293,5 +301,5 @@ Only if they are is the isBundleUpToDate flag set to true. That flag is used by backupHermesDebugAAR.dependsOn(backupHermesReleaseAAR) backupHermesReleaseAAR.dependsOn(copyJSBundle) copyJSBundle.dependsOn(buildJSBundle) - buildJSBundle.dependsOn(yarn_install, ensureAssetsDirectory) + buildJSBundle.dependsOn(yarn_install) } From 755671661f1509c75384d908686e33ac6c6bc0b0 Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 15 May 2020 20:17:06 +0300 Subject: [PATCH 4/4] Bump gradle Node plugin version, Node/Npm/Yarn too In the effort to fix the "Couldn't follow symbolic link." issue reported here: https://github.com/wordpress-mobile/WordPress-Android/pull/11921#issuecomment-629138944 --- react-native-gutenberg-bridge/android/build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/react-native-gutenberg-bridge/android/build.gradle b/react-native-gutenberg-bridge/android/build.gradle index 80124ab096..d5e39b7e3b 100644 --- a/react-native-gutenberg-bridge/android/build.gradle +++ b/react-native-gutenberg-bridge/android/build.gradle @@ -20,7 +20,7 @@ buildscript { classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' if (buildGutenbergMobileJSBundle) { - classpath "com.moowork.gradle:gradle-node-plugin:1.2.0" + classpath "com.moowork.gradle:gradle-node-plugin:1.3.1" } } } @@ -40,13 +40,13 @@ if (buildGutenbergMobileJSBundle) { node { // Version of node to use. - version = '12.13.1' + version = '12.16.1' // Version of npm to use. - npmVersion = '6.3.0' + npmVersion = '6.14.2' // Version of Yarn to use. - yarnVersion = '1.10.1' + yarnVersion = '1.22.4' // Base URL for fetching node distributions (change if you have a mirror). distBaseUrl = 'https://nodejs.org/dist'