Using Javascript Tools in the Build
Many times people just want to utilise a useful tool that is available from NPM, but they do not want to install a whole raft of global infrastructure just to use the tool. Also, they do not want other consumers of their build to have to do the same.
Approach 1: Bootstrapping everything
Let’s assume you want to run Antora with Gradle. You will need to set up some tasks to
-
Create a
package.json
file on your behalf. -
Populate it with the required Antora NPM packages.
-
Install them locally within your build space
ext {
antoraVersion = '2.2' (1)
}
nodejs {
useSystemPath() (2)
}
npm {
homeDirectory = "${buildDir}/antora" (3)
}
dependencies {
pnpm npm.pkg(scope: 'antora', name: 'cli', tag: antoraVersion, type: 'dev') (4)
pnpm npm.pkg(scope: 'antora', name: 'site-generator-default', tag: antoraVersion, type: 'dev')
}
task syncPackageJson(type: org.ysb33r.gradle.nodejs.tasks.SyncPackageJson) { (5)
forceSemver = false (6)
npmConfigurations 'pnpm' (7)
}
task installAntora(type: org.ysb33r.gradle.nodejs.tasks.NpmPackageJsonInstall) { (8)
dependsOn syncPackageJson
}
1 | Specify which version of Antora you are going to use. |
2 | Run Node with the system search path as Gradle otherwise Antora’s packages will not install correctly. |
3 | For this example we are keeping the source directory clean and running everything inside the build directory in a folder called antora . |
4 | Define the required Antora packages in the npm configuration. They are specified with type dev as they are purely used for running a tool. |
5 | Create a task that will bootstrap package.json . You don’t need to specify anything extra as this task knows from the npm extension where to create package.json |
6 | Create the synchronisation task that will write all the necessary package definitions into package.json |
7 | This task can only run if package.json has been created, so we need a dependency. |
8 | Because this is only running a tool, we do not really care about a properly formatted version. |
If you run ./gradlew installAntora
at this point you should see all the required Antora packages along with their transitive dependencies installed in build/antora/node_modules
. So what is left now is to add task which can actually execute Antora with different parameters. For this example we are only going to do the basic use case of running Antora with its playbook.
task runAntora { (1)
dependsOn installAntora (2)
doLast {
nodejs.exec { (3)
entrypoint {
workingDir npm.homeDirectoryProvider (4)
}
script {
path = npm.homeDirectoryProvider.map { new File(it, 'node_modules/@antora/cli/bin/antora') } (5)
args '../../antora-playbook.yml' (6)
}
}
}
}
1 | Create a basic task. |
2 | It needs to have Antora installed before it can run. |
3 | Use the nodeexec project extension to run node . |
4 | The working directory must be the same as where your Antora project is located i.e. the NPM home directory. |
5 | The location of the Antora script relative to the working directory. If you don’t know this, run installAntora first and then inspect the node_modules directory. |
6 | Provide some parameters for the task. In this case we are going to point to the location of the Antora playbook file relative to the working directory. If you want to try this example out you can get a demo playbook file. |
You are now left with just running ./gradlew runAntora
.
Approach 2: Supplying a package.json file
If you know enough about Node development you can craft up a package.json
file and have it in your project. This will reduce some of the code shown above.
nodejs {
useSystemPath() (1)
}
task installAntora( type : org.ysb33r.gradle.nodejs.tasks.NpmPackageJsonInstall ) (2)
1 | Run Node with the system search path as Gradle otherwise Antora’s packages will not install correctly. |
2 | Create a task that will download and install all the required NPM packages in the`node_modules` directory. If you place your package.json file in the project directory you do not need to make any more configuration. |
The package.json file does not have to be in the top of your project, but you will need to either copy it somewhere or be prepared to run the project in the folder whether this file exists and then exclude generated artifacts from source control. In this case you will have to configure the NpmPackageJsonInstall task.
|
You are now left with creating a task to run Antora. This is similar to before except that file locations will be different.
task runAntora {
dependsOn installAntora
doLast {
nodejs.exec {
entrypoint {
workingDir npm.homeDirectoryProvider
}
script {
path = 'node_modules/@antora/cli/bin/antora'
args 'antora-playbook.yml'
}
}
}
}
Run ./gradlew runAntora
and your site will be created.