Skip to content

Best Practices

Follow these guidelines for clean, maintainable Jakefiles.

Choose clear, self-documenting names:

# Good
task build-frontend:
npm run build
# Avoid
task bf:
npm run build

If you need shortcuts, use aliases:

task build-frontend | bf:
npm run build

Let users run jake without arguments:

@default
task dev:
npm run dev

Use section comments and @group for organization:

# === Build ===
@group build
task build: [build-frontend, build-backend]
echo "Build complete"
@group build
task build-frontend:
npm run build
@group build
task build-backend:
cargo build

Avoid unnecessary rebuilds:

# Good - only rebuilds when sources change
file dist/app.js: src/**/*.ts
esbuild src/index.ts --outfile=dist/app.js
# Avoid - rebuilds every time
task build:
esbuild src/index.ts --outfile=dist/app.js

Split large Jakefiles into modules:

project/
├── Jakefile
└── jake/
├── docker.jake
├── deploy.jake
└── test.jake
# Jakefile
@import "jake/docker.jake" as docker
@import "jake/deploy.jake" as deploy
@import "jake/test.jake" as test

Add descriptions for non-obvious tasks:

# Deploy to production
# Requires: AWS credentials, SSH key
# Usage: jake deploy env=production
@desc "Deploy to production servers"
task deploy env="staging":
@require AWS_ACCESS_KEY_ID
@confirm "Deploy to {{env}}?"
./scripts/deploy.sh {{env}}

Check dependencies before running commands:

@needs docker npm node
task build:
docker build -t myapp .
@require DATABASE_URL API_KEY
task deploy:
./deploy.sh

Pre-hooks for preparation, post-hooks for cleanup:

task test:
@pre docker-compose up -d
npm test
@post docker-compose down

Post-hooks run even if the recipe fails, making them ideal for cleanup.

Structure dependencies for parallel builds:

task frontend:
npm run build
task backend:
cargo build
task docs:
mkdocs build
# All three can run in parallel
task all: [frontend, backend, docs]
echo "Done!"
Terminal window
jake -j4 all # 4 parallel workers

Hide implementation details with underscore prefix or @hidden:

# Public interface
task build: [_setup, _compile, _bundle]
echo "Build complete!"
# Hidden implementation (underscore prefix)
task _setup:
mkdir -p dist
task _compile:
tsc
# Hidden implementation (@hidden directive)
@hidden
task bundle:
esbuild dist/index.js --bundle --outfile=dist/bundle.js

Use jake --all to see hidden recipes when debugging.

  • Default task set with @default
  • Descriptive names (with aliases if needed)
  • File targets for build artifacts
  • Requirements validated with @needs and @require
  • Complex recipes documented with @desc
  • Related tasks grouped logically
  • Private helpers hidden with _ prefix or @hidden
  • Cleanup handled with @post hooks