min read

How to use Gradle with Nx - simple - no plugin needed

While Nx is a really great tool to handle your monorepo builds and deployments, some of the plugins / extensions either conflict with the core packages, or pollute your workspace with boilerplate code. Third party plugins are sometimes worse regarding incompatibilities - I now tend to avoid them entirely and use plugins as little as possible.

It has cost me weeks of finding the cause of some superficial and verbose stack traces, such as


√ Installing @nx/nuxt@20.0.1...

- Initializing @nx/nuxt...

 NX  Generating @nx/nuxt:init

(node:8640) [DEP0180] DeprecationWarning: fs.Stats constructor is deprecated.

(Use `node --trace-deprecation ...` to show where the warning was created)

Convert compiler options from json failed, File '.nuxt/tsconfig.json' not found.

 NX   Cannot read properties of undefined (reading 'split')

Pass --verbose to see the stacktrace.

× Initializing @nx/nuxt...

Error: Command failed: pnpm exec nx g @nx/nuxt:init --keepExistingVersions --updatePackageScripts

    at genericNodeError (node:internal/errors:983:15)

    at wrappedFn (node:internal/errors:537:14)

    at checkExecSyncError (node:child_process:890:11)

    at execSync (node:child_process:962:15)

    at runNxSync (C:\Users\MyPC\Workspace\myproject\node_modules\nx\src\utils\child-process.js:28:34)

    at initializePlugin (C:\Users\MyPC\Workspace\myproject\node_modules\nx\src\command-line\add\add.js:106:39)

    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)

    at async C:\Users\MyPC\Workspace\myproject\node_modules\nx\src\command-line\add\add.js:26:9

    at async handleErrors (C:\Users\MyPC\Workspace\myproject\node_modules\nx\src\utils\handle-errors.js:9:24)

    at async Object.handler (C:\Users\MyPC\Workspace\myproject\node_modules\nx\src\command-line\add\command-object.js:25:22)

 NX   Failed to initialize @nx/nuxt. Please check the error above for more details.

See this GitHub issue

Custom Shell scripts

I maintain some scripts in my .github/scripts directory, that I frequently use in the script tags of the individual applications within.

One such example is used for Netlify deployments

Custom Netlify deployment script call in package.json Nx

The ${PROJECT_CWD} variable will be provided by Nx and give you the workspace root.

The -s flag controls if it's a static deployment or not

Integrating Gradle manually

I've adapted the same approach to Gradle with the simple idea to just pass the module and build command to it, and it will resolve - based on the OS - if it has to use the ./gradle.bat (Windows) or ./gradle (Linu😆 command, so it will work seamlessly in local environments and CI.


#!/bin/bash



# Check if a command is provided

if [ -z "$1" ]; then

  echo "Usage: $0 <gradle_command>"

  exit 1

fi



# Get the current workspace directory (the base directory of your Nx workspace)

WORKSPACE_DIR="$PROJECT_CWD"



# Detect OS

if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then

    echo "Running on Windows"

    GRADLE_COMMAND="./gradlew.bat"

else

    echo "Not running on Windows"

    GRADLE_COMMAND="./gradlew"

fi


echo "Now navigating to directory $WORKSPACE_DIR to run the Gradle command from"


# Change directory to the workspace root

cd "$WORKSPACE_DIR" || exit


# Run the specified Gradle command with the module path as an argument

eval "$GRADLE_COMMAND $1"

Similar to the previous Netlify script, I call it this way

Calling the Gradle script from package.json to trigger the build via Nx

And that's pretty much it.

Now a simple

yarn nx run @myapp/backend:build

will start the Gradle build without any additional Nx plugins.

Configured correctly, all the caching is handled by Gradle during the CI build, so you do not need any Nx specific setup.

In fact, this is now the project.json


{

  "name": "@myapp/backend",

  "$schema": "../../../node_modules/nx/schemas/project-schema.json",

  "projectType": "application",

  "tags": ["staging"]

}

Which does not even contain targets anymore and is super clean, and you have as little ties as possible to the tool.