It is cold, but · we have Sake · and the hot spring
Sake is a build tool and task runner for JavaScript. Sake features an extensible core and support for modern JS. Inspired by Cake, Sake is the perfect DSL for building projects.
- Additional helpers to make writing tasks faster and more pleasant.
- Generator based-control flow in tasks with full support for Promises.
- Intutive CLI and automatic option parsing.
- Plugin architecture with available plugins for many common build tasks.
- Tasks can declare dependencies and be easily composed of and interact with other tasks.
- Modern JS support:
- Async/Await
- ES modules
- Generators
- Promises
npm install sake-core --save-dev
Typically Sake is used via it's command line interface which can be installed
with npm install -g sake-cli
. Once the sake
command is
available, you can begin writing a Sakefile
and defining available tasks in
your project.
Sake will search for a Sakefile with tasks defined for your current project. Sakefiles can be written in ES2015 JavaScript and support modules natively.
Optionally, you can write your Sakefile in CoffeeScript, which allows a very nice DSL-ish experience.
Async tasks are easy to declare, any task with an obvious callback will be
treated as asynchronous. Add an additional argument called callback
, cb
,
done
or next
and use it to indicate when your task is finished executing.
task 'compile:js', 'compile js', (done) ->
exec 'coffee -bc app.coffee', done
task 'minify:js', 'minify js', (done) ->
exec 'uglify-js --compress --mangle app.js > app.min.js', done
You can also return a promise from your task and sake will automatically
wait for it to resolve. Since executive
returns a promise, this works too:
task 'compile:js', 'compile js', ->
exec 'coffee -bc app.coffee'
You can manually invoke tasks and string them together with callbacks:
task 'build', 'build project', ->
invoke 'compile:js', ->
invoke 'minify:js'
Dependencies can be declared by adding an array of task names after your task's description.
task 'build', 'build project', ['compile:js', 'minify:js']
You can also pass an array of tasks invoke
and it will execute them in order
for you:
task 'build', 'build project', (done) ->
invoke ['compile:js', 'minify:js'], done
...or more explicitly using invoke.serial
.
If you want to execute tasks in parallel you can use invoke.parallel
.
task 'compile', 'compile css & js', (done) ->
invoke.parallel ['compile:css', 'compile:js'], done
You can check for running tasks using the running
helper.
task 'watch', 'watch for changes and re-compile js', ->
exec 'coffee -bcmw -o lib/ src/'
task 'watch:test', 'watch for changes and re-run tests', (options) ->
invoke 'watch'
require('vigil').watch __dirname, (filename, stats) ->
return if running 'test'
if /^test/.test filename
invoke 'test', test: filename
if /^src/.test filename
invoke 'test'
You can also use yield
to wait for the value of a promise and eschew the use
of callbacks.
task 'compile:js', 'compile js', ->
yield exec 'coffee -bc app.coffee'
task 'minify:js', 'minify js', ->
yield exec 'uglify-js --compress --mangle app.js > app.min.js'
This really pays dividends with more complicated tasks:
task 'package', 'Package project', ->
yield exec '''
mkdir -p dist
rm -rf dist/*
'''
yield exec.parallel '''
cp manifest.json dist
cp -rf assets dist
cp -rf lib dist
cp -rf views dist
'''
yield exec '''
zip -r package.zip dist
rm -rf dist
'''
You can upgrade any Cakefile into a Sakefile by requiring sake-core
at the top
of your Cakefile.
You can peruse Sake's Sakefile for a real world example.