Jake is a simple and flexible JavaScript build tool for NodeJS. Jake has been around since the very early days of Node, and is full featured and well tested.
Jake is a CLI tool. You can install it globally with npm i -g jake, or install it locally and run with npx. You can even embed it as a module in larger programs.
Tasks for Jake to run are defined in Jakefiles. A Jakefile is just executable JavaScript. You can include whatever JS code you want in it.
Tasks are the basic building block of execution for Jake-based build processes. Tasks can have other tasks as prerequities, meaning those tasks have to run before the current task can run.
Concurrent tasks
Jake lets you run multiple asynchronous tasks at once, by making a task's prerequisites concurrent. You can control the amount of concurrency, with a passed option.
Tasks can be namespaced, which provides a flexible, powerful way to prevent name conflicts, or just provide some organization for your build.
When you use a filename as a prerequisite for a task, but there is not a file-task defined for it, Jake can create file-tasks on the fly from Rules.
Programmatic tasks
The invoke method allows you to run a task, along with its prerequisites, from inside another running task. This, along with the execute and reenable methods, make Jake infinitely programmable.
Jake will automatically look for files with a .js extension in a 'jakelib' directory in your project, and load them (using require) after loading your main Jakefile.

Give Jake a try, let us know what you think

Jake is the original build tool for JavaScript. Give it a try — we think you'll like what you see.