Split your Jakefile across multiple files with namespaced imports. Essential for monorepos and team collaboration.
@import "x.jake" as x # Jakefile
@import "jake/web.jake" as web
@import "jake/api.jake" as api
@import "jake/deploy.jake" as deploy
@default
task all: [web.build, api.build]
echo "All packages built!"
task release: [all, deploy.production]
echo "Released!" Organize tasks by concern. Each team or domain gets their own file.
project/
├── Jakefile # Main entry point
└── jake/
├── web.jake # Web team owns this
├── api.jake # API team owns this
├── mobile.jake # Mobile team owns this
└── deploy.jake # DevOps owns this monorepo/
├── Jakefile
├── packages/
│ ├── web/
│ │ ├── src/
│ │ └── package.json
│ ├── api/
│ │ ├── src/
│ │ └── package.json
│ └── shared/
│ └── src/
└── jake/
├── web.jake
├── api.jake
└── shared.jake Import files with a namespace, then reference tasks with the prefix.
# jake/web.jake
task build:
npm --prefix packages/web build
task dev:
npm --prefix packages/web dev
task test:
npm --prefix packages/web test as web creates the namespace web.build, web.dev, etc. $ jake -l
Available tasks:
all Build all packages
release Release to production
web.build Build web package
web.dev Start web dev server
web.test Run web tests
api.build Build API package
api.dev Start API dev server
deploy.staging Deploy to staging
deploy.production Deploy to production
$ jake web.build
→ web.build
✓ web.build (2.4s) Variables are scoped to their file. No accidental conflicts.
registry = "docker.io/mycompany"
task push:
docker push {{registry}}}/app registry = "gcr.io/my-project" # Different!
@import "docker.jake" as docker
task push:
echo {{registry}}} # gcr.io/my-project
# docker.push uses docker.io/mycompany Patterns for organizing large projects.
Each team maintains their own file. Merge conflicts are rare.
@import "jake/frontend.jake" as fe # Frontend team
@import "jake/backend.jake" as be # Backend team
@import "jake/infra.jake" as ops # DevOps team Separate deployment logic per environment.
@import "jake/staging.jake" as staging
@import "jake/production.jake" as prod
task deploy-staging: [build, staging.deploy]
task deploy-prod: [build, prod.deploy] Reusable utility tasks across projects.
# jake/utils.jake
task notify message:
curl -X POST $SLACK_WEBHOOK -d '{"text":"{{message}}"}'
# Jakefile
@import "jake/utils.jake" as utils
@after deploy utils.notify "Deployed!" Modules can depend on each other.
# jake/web.jake
@import "shared.jake" as shared
task build: [shared.build] # Depends on shared
npm run build
Make's include is global and fragile. Jake's imports are namespaced.
# Global include - variables and
# targets can conflict!
include scripts/docker.mk
include scripts/k8s.mk
# Which "build" is this? @import "scripts/docker.jake" as docker
@import "scripts/k8s.jake" as k8s
# Clear: docker.build vs k8s.build