Tasks

The plugin registers multiple tasks, that may have dependencies with each other, and also with:

  • Gradle lifecycle tasks defined in the Gradle Base plugin: clean, assemble, check.
  • Tasks defined in the Gradle Publishing plugin: publish.

Dependency tree

clean check assemble publish installNode installYarn installFrontend cleanFrontend checkFrontend assembleFrontend publishFrontend RunNode RunNpmYarn RunNpx Gradle Base plugin Gradle Publishing plugin Frontend Gradle plugin Additional task types

Reference

Built-in tasks

# Task installNode - Install Node.js

The task downloads a Node.js distribution, verifies its integrity, and installs it in the directory pointed by the nodeInstallDirectory property. The URL used to download the distribution is resolved using the nodeDistributionUrlRoot property and the nodeDistributionUrlPathPattern property. Checking the distribution integrity consists of downloading a file providing the distribution shasum. This file is expected to be in the same remote web directory than the distribution. For example, if the distribution is located at https://nodejs.org/dist/vX.Y.Z/node-vX.Y.Z-win-x64.zip, the plugin attempts to download the shasum file located at https://nodejs.org/dist/vX.Y.Z/SHASUMS256.txt. By default, the plugin relies on the VM network properties to know if a proxy server shall be used when downloading the distribution and the shasum. A custom proxy server may also be used by defining the httpsProxyHost property (respectively the httpProxyHost property) if the nodeDistributionUrlRoot property uses the https protocol (resp. uses the http protocol).

If a Node.js distribution is already installed in the local platform - either as a global installation or as an installation performed by another Gradle (sub-)project - and shall be used instead of a downloaded distribution, take a look at the nodeDistributionProvided property instead: when true, this task is ignored if invoked during a Gradle build, and its outcome will always be SKIPPED.

The task takes advantage of Gradle incremental build, and is not executed again unless one of its inputs/outputs changed. Consequently, if the task takes part of a Gradle build, its outcome will be UP-TO-DATE.

This task should not be executed directly. Gradle executes it if the build requires it.

# Task installYarn - Install Yarn

If the yarnEnabled property is true, the task downloads and install a Yarn distribution in the directory pointed by the yarnInstallDirectory. The URL used to download the distribution is resolved using the yarnDistributionUrlRoot property and the yarnDistributionUrlPathPattern property. By default, the plugin relies on the VM network properties to know if a proxy server shall be used when downloading the distribution. A custom proxy server may also be used by defining the httpsProxyHost property (respectively the httpProxyHost property) if the yarnDistributionUrlRoot property uses the https protocol (resp. uses the http protocol).

If a Yarn distribution is already installed in the local platform - either as a global installation or as an installation performed by another Gradle (sub-)project - and shall be used instead of a downloaded distribution, take a look at the yarnDistributionProvided property instead: when true, this task is ignored if invoked during a Gradle build, and its outcome will always be SKIPPED.

The task takes advantage of Gradle incremental build, and is not executed again unless one of its inputs/outputs changed. Consequently, if the task takes part of a Gradle build, its outcome will be UP-TO-DATE.

This task should not be executed directly. Gradle executes it if the build requires it.

# Task installFrontend - Install frontend dependencies

Depending on the value of the yarnEnabled property, this task issues either a npm install command or a yarn install command, by default. Consequently, the command shall install/update dependencies, and perform any additional actions as described in the package.json file located in the directory pointed by the packageJsonDirectory property. Optionally, this command may be customized with the installScript property (e.g. to run a npm ci command instead). This task depends on the installNode task, and optionally on the installYarn task if the yarnEnabled property is true.

About task execution

If you execute this task several times in a row, you may notice the npm/yarn command is always executed: Gradle does not skip the task based on a previous execution with the SUCCESS outcome. This is the expected behaviour because the task does not declare any input/output Gradle could track, to know the task is already UP-TO-DATE - unlike the installNode and installYarn tasks. Both npm and Yarn have their own strategy to limit overhead when dependencies are already up to date. The plugin does not duplicate this logic, considering it is the business of each package manager, and it would hardly perform as well. If you are tempted to tweak the task so as its execution is skipped under certain circumstances (e.g. declaring the large nodes_modules directory as an output), you would move this logic in Gradle. Gradle cannot do magic with large directories, and would have to track each file individually to determine whether the task should be executed or skipped. The question may be: is it worth moving the overhead to Gradle to skip task execution - maybe, or accepting the one occuring when npm/yarn is executed again? If you are about to tweak this task, take a look at these recommendations.

Some related discussions in Gradle forums: [1] [2] [3]

# Task cleanFrontend - Clean frontend artifacts

This task does nothing by default, considering frontend generated artifacts (minimified Javascript, CSS, HTML files...) are written in the ${project.buildDir} directory. If it is not the case, this task may be useful to clean the relevant directory. A clean script shall be defined in the package.json file, and the cleanScript property shall be set with the corresponding npm/yarn command. This task depends on the installFrontend task, and is skipped if the cleanScript property is null. Apart from direct execution, the task is also executed when the Gradle lifecycle clean task is executed.

# Task assembleFrontend - Assemble frontend artifacts

This task allows to execute a frontend build script as part of a Gradle build. The build script shall be defined in the package.json file, and the assembleScript property shall be set with the corresponding npm/yarn command. This task depends on the installFrontend task, and is skipped if the assembleScript property is null. Apart from direct execution, the task is also executed when the Gradle lifecycle assemble task is executed.
About task execution

If you execute this task several times in a row, you may notice the npm/yarn command is always executed: Gradle does not skip the task based on a previous execution with the SUCCESS outcome. This is the expected behaviour because the task does not declare any input/output Gradle could track, to know the task is already UP-TO-DATE - unlike the installNode and installYarn tasks. The task provides the ability to plug the developer's own Javascript build process to Gradle, and nothing more. Every Javascript build process is unique: it depends on the project, the languages involved (e.g. TypeScript, JSX, ECMA script, SASS, SCSS...), the directory layout, the build utilities (Webpack...), etc, chosen by the team. Moreover, some build utilities are already able to build frontend artifacts incrementally. The plugin does not duplicate this logic. If you are about to tweak this task, take a look at these recommendations.

# Task checkFrontend - Check frontend application

This task may be used to integrate a check script into a Gradle build. The check script shall be defined in the package.json file, and the checkScript property shall be set with the corresponding npm/yarn command. A typical check script may lint frontend source files, execute tests, and perform additional analysis actions. This task depends on the installFrontend task, and is skipped if the checkScript property is null. Apart from direct execution, the task is also executed when the Gradle lifecycle check task is executed.

# Task publishFrontend - Publish frontend artifacts

This task may be used to integrate a publish script into a Gradle build. The publish script shall be defined in the package.json file, and the publishScript property shall be set with the corresponding npm/yarn command. This task depends on the assembleFrontend task, and is skipped either if the assembleScript property is null, or if the publishScript property is null. Apart from direct execution, the task is also executed when the Gradle publish task is executed.

Additional types

# Type RunNode - Run a custom command with node

The plugin provides the task type org.siouan.frontendgradleplugin.infrastructure.gradle.RunNode that allows creating a custom task to run a JS script. The script property must be set with the corresponding command. Then, choose whether Node.js only is required, or if additional dependencies located in the package.json file should be installed: make the task either depends on installNode task or on installFrontend task. The code hereafter shows the configuration required to run a JS script:

import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNode
tasks.register('myScript', RunNode) {
    // dependsOn tasks.named('installNode')
    // dependsOn tasks.named('installFrontend')
    script = 'my-script.js'
}
import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNode
tasks.register<RunNode>("myScript") {
    // dependsOn(tasks.named("installNode"))
    // dependsOn(tasks.named("installFrontend"))
    script.set("my-script.js")
}

# Type RunNpmYarn - Run a custom command with npm or yarn

The plugin provides the task type org.siouan.frontendgradleplugin.infrastructure.gradle.RunNpmYarn that allows creating a custom task to run a frontend script. The script property must be set with the corresponding command. Depending on the yarnEnabled property, the task runs either npm or yarn. Then, choose the appropriate task dependency: make the task either depends on installNode task or on installFrontend task. The code hereafter shows the configuration required to run end-to-end tests:

import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNpmYarn
tasks.register('e2e', RunNpmYarn) {
    // dependsOn tasks.named('installNode')
    // dependsOn tasks.named('installFrontend')
    script = 'run e2e'
}
import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNpmYarn
tasks.register<RunNpmYarn>("e2e") {
    // dependsOn(tasks.named("installNode"))
    // dependsOn(tasks.named("installFrontend"))
    script.set("run e2e")
}

# Type RunNpx - Run a custom command with npx

Requires Node.js 8.2.0+ on Unix-like O/S, Node.js 8.5.0+ on Windows O/S

The plugin provides the task type org.siouan.frontendgradleplugin.infrastructure.gradle.RunNpx that allows creating a custom task to run a npx command. The script property must be set with the corresponding command. The task will fail if the yarnEnabled property is true, to prevent unpredictable behaviors with mixed installation of dependencies. Then, choose whether Node.js only is required, or if additional dependencies located in the package.json file should be installed: make the task either depends on installNode task or on installFrontend task. The code hereafter shows the configuration required to output the version of npx:

import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNpx
tasks.register('npxVersion', RunNpx) {
    // dependsOn tasks.named('installNode')
    // dependsOn tasks.named('installFrontend')
    script = '--version'
}
import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNpx
tasks.register<RunNpx>("npxVersion") {
    // dependsOn(tasks.named("installNode"))
    // dependsOn(tasks.named("installFrontend"))
    script.set("--version")
}

Tweaking the built-in tasks

If you need to customize the plugin's built-in tasks (e.g. declare additional I/O or dependencies), it is important to conform to the Configuration avoidance API: use references of task providers instead of references of tasks, and continue taking advantage of the lazy configuration strategy the plugin already implements. The examples below introduce the implementation expected with simple cases:

// Configuring a predefined task.
// FORMER SYNTAX: task 'installFrontend' is immediately created and configured, as well as task
// 'otherTask', even if both tasks are not executed.
installFrontend {
    dependsOn 'otherTask'
    inputs.files('package.json', 'package-lock.json')
}
// MODERN SYNTAX: task 'installFrontend' is created and configured only when Gradle is about to execute it.
// Consequently, task 'otherTask' is also created and configured later. Let's also reinforce this behaviour
// by using its provider to retrieve the task.
tasks.named('installFrontend') {
    dependsOn tasks.named('otherTask')
    inputs.files('package.json', 'package-lock.json')
}

// Defining a new task
// LEGACY SYNTAX: task 'eagerTask' is immediately created and configured, as well as task
// 'installFrontend', even if both tasks are not executed.
task eagerTask {
    dependsOn 'installFrontend'
}
// MODERN SYNTAX: task 'lazyTask' is created and configured only when Gradle is about to execute it.
// Consequently, task 'installFrontend' is also created and configured later. Let's also reinforce this
// behaviour by using its provider to retrieve the task.
tasks.register('lazyTask') {
    dependsOn tasks.named('installFrontend')
}
// Configuring a predefined task.
// FORMER SYNTAX: task 'installFrontend' is immediately created and configured, as well as task
// 'otherTask', even if both tasks are not executed.
installFrontend {
    dependsOn("otherTask")
    inputs.files("package.json", "package-lock.json")
}
// MODERN SYNTAX: task 'installFrontend' is created and configured only when Gradle is about to execute it.
// Consequently, task 'otherTask' is also created and configured later.
tasks.named<InstallTask>("installFrontend") {
    dependsOn(tasks.named("otherTask"))
    inputs.files("package.json", "package-lock.json")
}

// Defining a new task
// LEGACY SYNTAX: task 'eagerTask' is immediately created and configured, as well as task
// 'installFrontend', even if both tasks are not executed.
task eagerTask {
    dependsOn("installFrontend")
}
// MODERN SYNTAX: task 'lazyTask' is created and configured only when Gradle is about to execute it.
// Consequently, task 'installFrontend' is also created and configured later. Let's also reinforce this
// behaviour by using its provider to retrieve the task.
tasks.register("lazyTask") {
    dependsOn(tasks.named("installFrontend"))
}

If your application uses the legacy syntax, you may find further instructions to migrate to the modern syntax in this Gradle guide.