Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/guybedford/chomp
'JS Make' - parallel task runner for the frontend ecosystem with a JS extension system.
https://github.com/guybedford/chomp
Last synced: 12 days ago
JSON representation
'JS Make' - parallel task runner for the frontend ecosystem with a JS extension system.
- Host: GitHub
- URL: https://github.com/guybedford/chomp
- Owner: guybedford
- License: apache-2.0
- Created: 2021-12-05T22:45:45.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-04-03T22:15:31.000Z (7 months ago)
- Last Synced: 2024-04-13T22:02:36.054Z (7 months ago)
- Language: Rust
- Homepage: https://chompbuild.com
- Size: 14.1 MB
- Stars: 129
- Watchers: 6
- Forks: 7
- Open Issues: 25
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# CHOMP
[![Crates.io](https://img.shields.io/badge/crates.io-chompbuild-green.svg)](https://crates.io/crates/chompbuild)
[![Discord](https://img.shields.io/badge/chat-on%20discord-green.svg?logo=discord)](https://discord.gg/5E9zrhguTy)Chomp is a frontend task runner with advanced features focused on _ease-of-use_ and _not getting in the way_!
1. An advanced task runner with a single command!
1. Easily adapt existing projects / task systems - no need for a rewrite.
1. You enable and manage advanced task runner features with single-line updates.Chomp is a great option for frontend projects where the goal is getting advanced task runner features (like smart caching) without complexity and overhead.
## One-line migration from npm scripts
Chomp can import a project's established `package.json` scripts without breaking them, as it supports the same features:
```bash
chomp --init --import-scripts
```Now you can run your npm scripts using Chomp!
> i.e `npm run ` becomes `chomp ` and behaves the same, and you can opt in to further features as needed.
The only difference is, with Chomp — it's faster. And, with a few more tweaks, you can enable smart caching, parallelism, and more!
## What features does Chomp provide?
Chomp is an advanced task runner. It provides features similar to [turbo](https://turbo.build/repo) and [nx](https://nx.dev/) but focuses on ease of use, *not monorepos. It's based on the same principles as traditional make files.
### Parallelism
Chomp [runs tasks in parallel](./docs/task.md#serial-dependencies), based on an extecuted task's dependencies!
### Watch/Serve
Chomp [watches any task](./docs/task.md#watched-rebuilds) by including a `--watch` or `--serve` option! Read more about the power of [`--watch`](./docs/task.md#watched-rebuilds) and [`--serve`](./docs/task.md#static-server).
### A JS extension system
Chomp has a [JS extension system](./docs/extensions.md) that allows you to extend Chomp with your own custom tasks
### Smart caching
Chomp [caches tasks](./docs/task.md#task-caching) based on task dependencies like other tasks or updated files. You don't have to worry about it!
> \*Chomp works for monrepos but it's architected for ease of use and not getting in the way first.
## Install
If you use [Cargo](https://rustup.rs/), run:
```
cargo install chompbuild
```If you don't use Cargo, run:
```
npm install -g chomp
```> Note: npm scripts add over 100ms to the script run time.
Common platform binaries are also available for [all releases](https://github.com/guybedford/chomp/releases).
To quickly set up Chomp in a GitHub Actions CI workflow, see the [Chomp GitHub Action](https://github.com/guybedford/chomp-action).
## Documentation
* [CLI Usage](https://github.com/guybedford/chomp/blob/main/docs/cli.md)
* [Chompfile Definitions](https://github.com/guybedford/chomp/blob/main/docs/chompfile.md)
* [Task Definitions](https://github.com/guybedford/chomp/blob/main/docs/task.md)
* [Extensions](https://github.com/guybedford/chomp/blob/main/docs/extensions.md)## Getting Started
### Migrating from npm Scripts
To convert an existing project using npm `"scripts"` to Chomp, run:
```sh
$ chomp --init --import-scripts
√ chompfile.toml created with 2 package.json script tasks imported.
```or the shorter version:
```sh
$ chomp -Ii
√ chompfile.toml created with 2 package.json script tasks imported.
```Then use `chomp ` instead of `npm run `, and enjoy the new features of task dependence, incremental builds, and parallelism!
### Hello World
`chomp` works against a [`chompfile.toml`](https://github.com/guybedford/chomp/blob/main/docs/chompfile.md) [TOML configuration](https://toml.io/) in the same directory as the `chomp` command is run.
Chomp builds up tasks as trees of files which depend on other files, then runs those tasks with [maximum parallelism](https://github.com/guybedford/chomp/blob/main/docs/task.md#task-dependence).
For example, here's a task called `hello` which builds `hello.txt` based on the contents of `name.txt`, which itself is built by another command:
chompfile.toml
```toml
version = 0.1[[task]]
target = 'name.txt'
run = '''
echo "No name.txt, writing one."
echo "World" > name.txt
'''[[task]]
name = 'hello'
target = 'hello.txt'
dep = 'name.txt'
run = '''
echo "Hello $(cat name.txt)" > hello.txt
'''
```with this file saved, the hello command will run all dependency commands before executing its own command:
```sh
$ chomp hello🞂 name.txt
No name.txt, writing one.
√ name.txt [4.4739ms]
🞂 hello.txt
√ hello.txt [5.8352ms]$ cat hello.txt
Hello World
```Finally it populates the `hello.txt` file with the combined output.
Subsequent runs use the mtime of the target files to determine what needs to be rerun.
Rerunning the `hello` command will see that the `hello.txt` target is defined, and that the `name.txt` dependency didn't change, so it will skip running the command again:
```sh
chomp hello● name.txt [cached]
● hello.txt [cached]
```Changing the contents of `name.txt` will then invalidate the `hello.txt` target only, not rerunning the `name.txt` command:
```sh
$ echo "Chomp" > name.txt
$ chomp hello● name.txt [cached]
hello.txt invalidated by name.txt
🞂 hello.txt
√ hello.txt [5.7243ms]$ cat hello.txt
Hello Chomp
```The [`deps`](https://github.com/guybedford/chomp/blob/main/docs/task.md#task-dependence) array can be defined for targets, whose targets will then be run first with [invalidation based on target / deps mtime comparisons](https://github.com/guybedford/chomp/blob/main/docs/task.md#task-caching) per the standard Makefile approach.
Powershell is used on Windows, while Bash is used on POSIX systems. Since both `echo` and `>` are defined on both systems, the examples above work cross-platform (Powershell is automatically put into UTF-8 mode for `>` to work similarly).
Note that `&&` and `||` are not supported in Powershell, so multiline scripts and `;` are preferred instead.
#### JS Tasks
Alternatively we can use `engine = 'node'` or `engine = 'deno'` to write JavaScript in the `run` function instead:
chompfile.toml
```toml
version = 0.1[[task]]
target = 'name.txt'
engine = 'node'
run = '''
import { writeFile } from 'fs/promises';
console.log("No name.txt, writing one.");
await writeFile(process.env.TARGET, 'World');
'''[[task]]
name = 'hello'
target = 'hello.txt'
deps = ['name.txt']
engine = 'node'
run = '''
import { readFile, writeFile } from 'fs/promises';
const name = (await readFile(process.env.DEP, 'utf8')).trim();
await writeFile(process.env.TARGET, `Hello ${name}`);
'''
```Tasks are run with maximum parallelism as permitted by the task graph, which can be controlled via the [`-j` flag](https://github.com/guybedford/chomp/blob/main/docs/cli.md#jobs) to limit the number of simultaneous executions.
Using the [`--watch` flag](https://github.com/guybedford/chomp/blob/main/docs/cli.md#watch) watches all dependencies and applies incremental rebuilds over invalidations only.
Or, using `chomp hello --serve` runs a [static file server](https://github.com/guybedford/chomp/blob/main/docs/task.md#static-server) with watched rebuilds.
See the [task documentation](https://github.com/guybedford/chomp/blob/main/docs/task.md) for further details.
#### Monorepos
There is no first-class monorepo support in chomp, but some simple techniques can achieve the same result.
For example, consider a monorepo where `packages/[pkgname]/chompfile.toml` defines per-package tasks.
A base-level `chompfile.toml` could run the `test` task of all the sub-packages with the following `chompfile.toml`:
```toml
[[task]]
name = 'test'
dep = 'packages/#/chompfile.toml'
run = 'chomp -c $DEP test'
````chomp test` will then use [task interpolation](https://github.com/guybedford/chomp/blob/main/docs/task.md#task-interpolation) to run the multiple sub-package test tasks in parallel. A similar approach can also be used for a [basic unit testing](https://github.com/guybedford/chomp/blob/main/docs/task.md#testing).
By adding [`serial = 'true'`](https://github.com/guybedford/chomp/blob/main/docs/task.md#serial-dependencies), the interpolation can be made to run in series rather than in parallel.
Cross-project dependencies are [not currently supported](https://github.com/guybedford/chomp/issues/119). Instead, if `packages/a/chompfile.toml`'s build task depends on `packages/b/chompfile.toml`'s build task to run first, then `packages/a/chompfile.toml` might look like:
```toml
[[task]]
name = 'build'
run = 'cargo build'
dep = 'build:deps'[[task]]
name = 'build:deps'
run = 'chomp -c ../a build'
```This would still be fast, so long as `packages/a/chompfile.toml`'s `build` task has its targets and dependencies properly configured to do zero work if the all target mtimes are greater than their dependencies.
### Extensions
Extensions are able to register task templates for use in Chompfiles.
Extensions are loaded using the `extensions` list, which can be any local or remote JS file:
```toml
version = 0.1
extensions = [
"./local.js",
"https://remote.com/extension.js"
]
```A core extensions library is provided with useful templates for the JS ecosystem, with
the short protocol `chomp:ext`, a shorthand for the `@chompbuild/extensions` package contents.A simple example is included below.
_See the [@chompbuild/extensions package](https://github.com/guybedford/chomp-extensions) for extension descriptions and examples._
#### Example: TypeScript with SWC
To compile TypeScript with the SWC template:
```toml
version = 0.1
extensions = ['[email protected]:swc'][[task]]
name = 'build:typescript'
template = 'swc'
target = 'lib/##.js'
deps = ['src/##.ts']
```In the above, all `src/**/*.ts` files will be globbed, have SWC run on them, and output into `lib/[file].js` along with their source maps.
The `##` and `#` interpolation syntax is special because, unlike glob dependencies (which are also supported), there must be a 1:1 relationship between a dependency and its target.
Only non-existent files, or files whose `src` mtimes are invalidated will be rebuilt. If SWC itself is updated, all files that depend on it will be re-built.
Specific files or patterns can be built directly by name as well, skipping all other build work:
```sh
chomp lib/main.js lib/dep.js🞂 lib/dep.js
🞂 lib/app.js
√ lib/dep.js [317.2838ms]
√ lib/app.js [310.0831ms]
```Patterns are also supported for building tasks by name or filename (the below two commands are equivalent):
```sh
$ chomp lib/*.js
$ chomp :build:*
```To remove the template magic, run `chomp --eject` to convert the `chompfile.toml` into its untemplated form:
```sh
$ chomp --eject√ chompfile.toml template tasks ejected
```Resulting in the updated _chompfile.toml_:
```toml
version = 0.1[[task]]
name = 'build:typescript'
target = 'lib/##.js'
dep = 'src/##.ts'
stdio = 'stderr-only'
run = 'node ./node_modules/@swc/cli/bin/swc.js $DEP -o $TARGET --no-swcrc --source-maps -C jsc.parser.syntax=typescript -C jsc.parser.importAssertions=true -C jsc.parser.topLevelAwait=true -C jsc.parser.importMeta=true -C jsc.parser.privateMethod=true -C jsc.parser.dynamicImport=true -C jsc.target=es2016 -C jsc.experimental.keepImportAssertions=true'
```# License
Apache-2.0