diff --git a/react-native-gutenberg-bridge/android/build.gradle b/react-native-gutenberg-bridge/android/build.gradle index 033357aefa..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' @@ -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 { @@ -163,21 +170,89 @@ 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 bundleName = 'index.android.bundle' + 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.") + + 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 + } + } - task buildJSBundle(type: YarnTask) { - args = ['bundle:android'] - } + dirs.forEach { dir -> + file(dir).eachFileRecurse { + if (isRelevantFile(it)) { + jsFiles << it + } + } + } - task ensureAssetsDirectory { + 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("$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 { - mkdir assetsFolder + // 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() } } + yarn_install.dependsOn bundleUpToDateCheck + yarn_install.onlyIf { !isBundleUpToDate() } + + task buildJSBundle(type: YarnTask) { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + + args = ['bundle:android'] + } + task backupHermesDebugAAR(type: Copy) { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + def origFileName = 'hermes-debug.aar' def origWithPath = hermesOriginalPath + origFileName from origWithPath @@ -188,6 +263,9 @@ if (buildGutenbergMobileJSBundle) { } task backupHermesReleaseAAR(type: Copy) { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + def origFileName = 'hermes-release.aar' def origWithPath = hermesOriginalPath + origFileName from origWithPath @@ -198,27 +276,30 @@ if (buildGutenbergMobileJSBundle) { } task copyJSBundle(type: Copy) { + dependsOn bundleUpToDateCheck + onlyIf { !isBundleUpToDate() } + 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" } } 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) }