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

checkassemblepublishinstallNodeinstallCorepackresolvePackageManagerinstallPackageManagerinstallFrontendcheckFrontendassembleFrontendpublishFrontendrunNoderunCorepackrunNpmrunPnpmrunYarnRunNodeTaskTypeRunCorepackTaskTypeRunNpmTaskTypeRunPnpmTaskTypeRunYarnTaskTypeGradle Base pluginGradle Publishing pluginFrontend Gradle pluginLifecycle tasksInstant tasksTask types

Reference

Lifecycle 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 archive. 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 httpsProxyHost property (respectively httpProxyHost property) if the nodeDistributionUrlRoot property uses the https protocol (resp. uses the http protocol). In case of connectivity/HTTP error, download of the distribution file and the shasum file may be retried using property maxDownloadAttempts.

If a Node.js distribution is already installed in the system, 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. In this case, the task outcome will be UP-TO-DATE.

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

# Task installCorepack - Install/upgrade Corepack

The purpose of this task is to allow replacing the default version of Corepack embedded in Node.js. This may be necessary in case of Corepack fails to install the package manager used by the project, or to continuously benefit from the latest improvements and bug fixes. By default, this task is not executed unless property corepackVersion is defined with a non-null value. In the latter case, the plugin executes command npm install -g corepack[@<corepackVersion>]. Apart from a specific version number, if this property is set with the latest value, the plugin installs the latest version available. Note that this task will not be executed again and update Corepack automatically if a newer version is released after this task has run once successfully. Since the project may use a package manager that is not npm, the task disables Corepack strict behavior when running npm (see environment variable COREPACK_ENABLE_STRICT).

As the task touches the Node.js install directory, please pay attention when using a shared Node.js distribution (nodeDistributionProvided is true), because this task will impact other projects using Corepack. This may be desirable or not depending on your situation.

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

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

# Task resolvePackageManager - Resolve package manager C

The behavior of this task depends on the existence of the package.json file:

  • If the package.json file exists, the task identifies the name and the version of the package manager applicable to the project by parsing the packageManager property. For example, if the package.json file contains "packageManager": "npm@10.9.0", the task resolves npm as the name of the package manager, and 10.9.0 as its version.
  • If the package.json file does not exist, the task removes output files to prevent side effects with other tasks provided by the plugin.

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

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

# Task installPackageManager - Install package manager

The task installs the package manager resolved with task resolvePackageManager, by executing command corepack enable <package-manager>.

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 package manager, this task executes either command npm install, or command pnpm install, or command yarn install, by default. Consequently, the command shall install project dependencies according to the algorithm followed by each package manager (see hereafter). Optionally, this command may be customized with the installScript property (e.g. to run a npm ci command instead). On a developer workstation, executing this task is a good starting point to setup a workspace for development as it will install the Node.js distribution (if not provided) as well as dependencies.

About incremental build and up-to-date checks

If you execute this task several times in a row, you may notice the npm/pnpm/yarn command is always executed: Gradle does not reuse task outputs based on a previous execution with the SUCCESS outcome. This is the expected behaviour by default because the task does not declare any relevant input(s) and output(s) Gradle could track to know the task is already UP-TO-DATE (e.g. unlike the installNode task). Resolving these inputs/outputs is a bit complex, since it depends on the package manager, the value of the installScript property, and the files present in the project. That's why incremental build for this task is not available out-of-the-box by now. However, some examples provide guidelines to customize this task and limit executions under certain circumstances. Notes hereafter provide also some unofficial ideas:

  • npm: inputs may be one or more of files package.json, npm-shrinkwrap.json, package-lock.json, yarn.lock, while outputs may be the node_modules directory and the package-lock.json file (see npm install). If the installScript property is set with ci, file package-lock.json or file npm-shrinkwrap.json may be the only possible input file, if one or the other exists, and the node_modules directory the only output.
  • pnpm: inputs may be one or more of files package.json, pnpm-lock.yaml, while outputs may be the node_modules directory and the pnpm-lock.yaml file.
  • Yarn: inputs may be one or more of files package.json, yarn.lock, while outputs may be the node_modules directory, or the .pnp.cjs file and the .yarn/cache directory (Zero-installs), and the yarn.lock file.

If you are about to tweak this task to declare additional inputs and outputs, take a look at these recommendations.

# Task assembleFrontend - Assemble frontend artifacts

This task allows to execute a 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/pnpm/yarn command. Apart from direct execution, the task is also executed when the Gradle lifecycle assemble task is executed.
About incremental build and up-to-date checks

If you execute this task several times in a row, you may notice the npm/pnpm/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 (e.g. unlike task installNode). 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 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/pnpm/yarn command. A typical check script may lint source files, execute tests, and/or perform additional analysis actions. 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/pnpm/yarn command. Apart from direct execution, the task is also executed when the Gradle publish task is executed.

Instant tasks

# Task runNode - Run an instant command with node from Gradle command line

This task allows to execute a node command from a Gradle command line. To define custom inputs, outputs, or environment, it is recommended to register a custom task using RunNodeTaskType rather than overriding the default configuration of this task.

# Task runCorepack - Run an instant command with corepack from Gradle command line

This task allows to execute a corepack command from a Gradle command line. To define custom inputs, outputs, or environment, it is recommended to register a custom task using RunCorepackTaskType rather than overriding the default configuration of this task.

# Task runNpm - Run an instant command with npm from Gradle command line

This task allows to execute a npm command from a Gradle command line. To define custom inputs, outputs, or environment, it is recommended to register a custom task using RunNpmTaskType rather than overriding the default configuration of this task.

# Task runPnpm - Run an instant command with pnpm from Gradle command line

This task allows to execute a pnpm command from a Gradle command line. To define custom inputs, outputs, or environment, it is recommended to register a custom task using RunPnpmTaskType rather than overriding the default configuration of this task.

# Task runYarn - Run an instant command with yarn from Gradle command line

This task allows to execute a yarn command from a Gradle command line. To define custom inputs, outputs, or environment, it is recommended to register a custom task using RunYarnTaskType rather than overriding the default configuration of this task.

Task types

# Type RunNodeTaskType - Register a task running a custom command with node

Task type org.siouan.frontendgradleplugin.infrastructure.gradle.RunNodeTaskType allows to register a custom task executing a node command. The args property must be defined with the corresponding arguments, either in the build script or on the command line. The example hereafter shows how to register a task in a build script to output the version of node:

import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNodeTaskType
tasks.register('customNodeTask', RunNodeTaskType) {
    dependsOn 'installNode'
    // If the command requires additional dependencies located in the 'package.json' file,
    // replace the previous task dependency with the one hereafter:
    //dependsOn 'installFrontend'
    args = '-v'
}
import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNodeTaskType
tasks.register<RunNodeTaskType>("customNodeTask") {
    dependsOn("installNode")
    // If the command requires additional dependencies located in the 'package.json' file,
    // replace the previous task dependency with the one hereafter:
    //dependsOn("installFrontend")
    args.set("-v")
}

The args property may be defined or overwritten on the command line: gradle customNodeTask "--args=-v"

# Type RunCorepackTaskType - Register a task running a custom command with corepack

Task type org.siouan.frontendgradleplugin.infrastructure.gradle.RunCorepackTaskType allows to register a custom task executing a corepack command. The args property must be defined with the corresponding arguments, either in the build script or on the command line. The example hereafter shows how to register a task in a build script to output the version of corepack:

import org.siouan.frontendgradleplugin.infrastructure.gradle.RunCorepackTaskType
tasks.register('customCorepackTask', RunCorepackTaskType) {
    dependsOn 'installCorepack'
    args = '-v'
}
import org.siouan.frontendgradleplugin.infrastructure.gradle.RunCorepackTaskType
tasks.register<RunCorepackTaskType>("customCorepackTask") {
    dependsOn("installCorepack")
    args.set("-v")
}

The args property may be defined or overwritten on the command line: gradle customCorepackTask "--args=-v"

# Type RunNpmTaskType - Register a task running a custom command with npm

Task type org.siouan.frontendgradleplugin.infrastructure.gradle.RunNpmTaskType allows to register a custom task executing a npm command. The args property must be defined with the corresponding arguments, either in the build script or on the command line. The example hereafter shows how to register a task in a build script to output the version of npm:

import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNpmTaskType
tasks.register('customNpmTask', RunNpmTaskType) {
    dependsOn 'installPackageManager'
    // If the command requires additional dependencies located in the 'package.json' file,
    // replace the previous task dependency with the one hereafter:
    //dependsOn 'installFrontend'
    args = '-v'
}
import org.siouan.frontendgradleplugin.infrastructure.gradle.RunNpmTaskType
tasks.register<RunNpmTaskType>("customNpmTask") {
    dependsOn("installPackageManager")
    // If the command requires additional dependencies located in the 'package.json' file,
    // replace the previous task dependency with the one hereafter:
    //dependsOn("installFrontend")
    args.set("-v")
}

The args property may be defined or overwritten on the command line: gradle customNpmTask "--args=-v"

# Type RunPnpmTaskType - Register a task running a custom command with pnpm

Task type org.siouan.frontendgradleplugin.infrastructure.gradle.RunPnpmTaskType allows to register a custom task executing a pnpm command. The args property must be defined with the corresponding arguments, either in the build script or on the command line. The example hereafter shows how to register a task in a build script to output the version of pnpm:

import org.siouan.frontendgradleplugin.infrastructure.gradle.RunPnpmTaskType
tasks.register('customPnpmTask', RunPnpmTaskType) {
    dependsOn 'installPackageManager'
    // If the command requires additional dependencies located in the 'package.json' file,
    // replace the previous task dependency with the one hereafter:
    //dependsOn 'installFrontend'
    args = '-v'
}
import org.siouan.frontendgradleplugin.infrastructure.gradle.RunPnpmTaskType
tasks.register<RunPnpmTaskType>("customPnpmTask") {
    dependsOn("installPackageManager")
    // If the command requires additional dependencies located in the 'package.json' file,
    // replace the previous task dependency with the one hereafter:
    //dependsOn("installFrontend")
    args.set("-v")
}

The args property may be defined or overwritten on the command line: gradle customPnpmTask "--args=-v"

# Type RunYarnTaskType - Register a task running a custom command with yarn

Task type org.siouan.frontendgradleplugin.infrastructure.gradle.RunYarnTaskType allows to register a custom task executing a yarn command. The args property must be defined with the corresponding arguments, either in the build script or on the command line. The example hereafter shows how to register a task in a build script to output the version of yarn:

import org.siouan.frontendgradleplugin.infrastructure.gradle.RunYarnTaskType
tasks.register('customYarnTask', RunYarnTaskType) {
    dependsOn 'installPackageManager'
    // If the command requires additional dependencies located in the 'package.json' file,
    // replace the previous task dependency with the one hereafter:
    //dependsOn 'installFrontend'
    args = '-v'
}
import org.siouan.frontendgradleplugin.infrastructure.gradle.RunYarnTaskType
tasks.register<RunYarnTaskType>("customYarnTask") {
    dependsOn("installPackageManager")
    // If the command requires additional dependencies located in the 'package.json' file,
    // replace the previous task dependency with the one hereafter:
    //dependsOn("installFrontend")
    args.set("-v")
}

The args property may be defined or overwritten on the command line: gradle customYarnTask "--args=-v"

Environment variables in node-based tasks

The plugin provides multiple tasks or types that execute under-the-hood a node-based command: installCorepack, installPackageManager, installFrontend, assembleFrontend, checkFrontend, publishFrontend, RunNodeTaskType, RunCorepackTaskType, RunNpmTaskType, RunPnpmTaskType, RunYarnTaskType. These tasks forward environment variables visible by the Gradle process to node, corepack, npm, pnpm, yarn commands. These variables may be overwritten and/or new variables may be added to the environment forwarded to the command. If you need to alter the PATH environment variable, and though this is generally a rare situation, keep in mind the plugin adds its own paths so as the relevant node executable can be found.

Example hereafter shows how to customize the environment for a given task:


import org.siouan.frontendgradleplugin.infrastructure.gradle.AssembleTask
tasks.named('assembleFrontend', AssembleTask) {
    environmentVariables.put('NODE_OPTIONS', '--max_old_space_size=50 --title="Assembling frontend"')
}

import org.siouan.frontendgradleplugin.infrastructure.gradle.AssembleTask
tasks.named<AssembleTask>("assembleFrontend") {
    environmentVariables.put("NODE_OPTIONS", "--max_old_space_size=50 --title=\"Assembling frontend\"")
}

Example hereafter shows how to apply an environment variable to all tasks running a node-based command:


import org.siouan.frontendgradleplugin.infrastructure.gradle.AbstractRunCommandTask
tasks.withType(AbstractRunCommandTask) {
    environmentVariables.put('NODE_DEBUG', 'module')
}

import org.siouan.frontendgradleplugin.infrastructure.gradle.AbstractRunCommandTask
tasks.withType<AbstractRunCommandTask> {
    environmentVariables.put("NODE_DEBUG", "module")
}

Built-in tasks customization

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.
// LEGACY 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 '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 'installFrontend'
}
// Configuring a predefined task.
// LEGACY 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<InstallFrontendTask>("installFrontend") {
    dependsOn("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("installFrontend")
}

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