• Stars
    star
    141
  • Rank 259,971 (Top 6 %)
  • Language
    Rust
  • License
    Apache License 2.0
  • Created almost 3 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

'JS Make' - parallel task runner for the frontend ecosystem with a JS extension system.

CHOMP

Crates.io Discord

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!
  2. Easily adapt existing projects / task systems - no need for a rewrite.
  3. 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:

chomp --init --import-scripts

Now you can run your npm scripts using Chomp!

i.e npm run <task> becomes chomp <task> 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 and nx 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, based on an extecuted task's dependencies!

Watch/Serve

Chomp watches any task by including a --watch or --serve option! Read more about the power of --watch and --serve.

A JS extension system

Chomp has a JS extension system that allows you to extend Chomp with your own custom tasks

Smart caching

Chomp caches tasks 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, 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.

To quickly set up Chomp in a GitHub Actions CI workflow, see the Chomp GitHub Action.

Documentation

Getting Started

Migrating from npm Scripts

To convert an existing project using npm "scripts" to Chomp, run:

$ chomp --init --import-scripts
√ chompfile.toml created with 2 package.json script tasks imported.

or the shorter version:

$ chomp -Ii
√ chompfile.toml created with 2 package.json script tasks imported.

Then use chomp <name> instead of npm run <name>, and enjoy the new features of task dependence, incremental builds, and parallelism!

Hello World

chomp works against a chompfile.toml TOML configuration 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.

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

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:

$ 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:

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:

$ 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 array can be defined for targets, whose targets will then be run first with invalidation based on target / deps mtime comparisons 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

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 to limit the number of simultaneous executions.

Using the --watch flag watches all dependencies and applies incremental rebuilds over invalidations only.

Or, using chomp hello --serve runs a static file server with watched rebuilds.

See the task documentation 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:

[[task]]
name = 'test'
dep = 'packages/#/chompfile.toml'
run = 'chomp -c $DEP test'

chomp test will then use task interpolation to run the multiple sub-package test tasks in parallel. A similar approach can also be used for a basic unit testing.

By adding serial = 'true', the interpolation can be made to run in series rather than in parallel.

Cross-project dependencies are not currently supported. 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:

[[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:

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 for extension descriptions and examples.

Example: TypeScript with SWC

To compile TypeScript with the SWC template:

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:

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):

$ chomp lib/*.js
$ chomp :build:*

To remove the template magic, run chomp --eject to convert the chompfile.toml into its untemplated form:

$ chomp --eject

√ chompfile.toml template tasks ejected

Resulting in the updated chompfile.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

More Repositories

1

es-module-shims

Shims for new ES modules features on top of the basic modules support in browsers
JavaScript
1,514
star
2

require-css

A RequireJS CSS loader plugin to allow CSS requires and optimization
JavaScript
983
star
3

es-module-lexer

Low-overhead lexer dedicated to ES module parsing for fast analysis
JavaScript
791
star
4

require-less

LESS loader plugin for RequireJS with builds, based on RequireCSS
JavaScript
139
star
5

wasm-intro

Egghead.io WASM Introduction Examples
HTML
119
star
6

wasm-demo

Egghead.io WASM Introduction Demo Project
HTML
107
star
7

isomorphic-browser-modules

A workflow for using <script type="module"> with a fallback for older browsers
JavaScript
51
star
8

require-is

Conditional loader plugin for RequireJS with code branch build support
JavaScript
51
star
9

amd-loader

RequireJS loader plugin helper for transpiler and template plugins
JavaScript
34
star
10

import-maps-extensions

Extensions to the WICG import maps proposal
HTML
30
star
11

systemjs-webpack-plugin

Webpack bundling for SystemJS
JavaScript
28
star
12

wasm-stdlib-hack

Copy of libc and libcxx includes from Emscripten with some wast linking helpers
C++
25
star
13

markdown-component

JavaScript
21
star
14

proposal-weak-imports

Experimental Weak Imports Proposal for ECMAScript
HTML
20
star
15

cjs

CommonJS loader plugin for RequireJS
JavaScript
17
star
16

jspm-react-component-demo

JavaScript
14
star
17

react-jspm-es6-gulp-example

a work in progress example showing react / react-nested-router / jspm / gulp / es6
JavaScript
14
star
18

system-md

jspm Markdown plugin
JavaScript
12
star
19

es6

ES6 Loader Plugin for RequireJS
JavaScript
10
star
20

packagemap-polyfill

Experimental polyfill approach for package name maps in browsers
JavaScript
10
star
21

js-components

WebAssembly
9
star
22

require-inline

A small add-on for RequireJS providing inline sync load support. Useful for dynamic widgets that need JavaScript attachments to occur instantly during the page load.
JavaScript
8
star
23

amdquery

A selector plugin for RequireJS with a dynamic query selector polyfill, supporting modular DOM utilities and builds.
JavaScript
6
star
24

jspm-beta-guide

5
star
25

proposal-export-star-default

Proposal to include default export in `export * from 'module'`
HTML
5
star
26

chomp-extensions

Chomp template collection
JavaScript
5
star
27

proposal-pkg-entries

package.json "entries" field proposal
4
star
28

systemjs-istanbul

SystemJS Istanbul Coverage Helper
JavaScript
4
star
29

chomp-action

GitHub Action to Install Chomp
JavaScript
4
star
30

wasi_unstable

WASI Unstable Experimental ES Module Integration
JavaScript
4
star
31

node-resolve-hook

Draft proposal for NodeJS ES modules pipeline hooks
4
star
32

karma-systemjs-experiment

JavaScript
3
star
33

jspm-demo

JavaScript
3
star
34

extract-requires

Extract CommonJS requires from a JavaScript source string with simple tokenizing
JavaScript
3
star
35

modules-caching

JavaScript
2
star
36

cjs-named-exports-loader

JavaScript
2
star
37

jspm-test-demo

jspm test demo
JavaScript
2
star
38

proposal-pkg-targets

package.json proposal for differential target resolution
2
star
39

hbs

JavaScript
2
star
40

babel-modules-system-source-maps-bug

JavaScript
1
star
41

plugin-traceur

SystemJS Traceur Plugin (wip)
1
star
42

voxel-demo

JavaScript
1
star
43

json

AMD wrapper module for JSON parsing. Feature detects JSON.stringify and JSON.parse, dynamically requesting json2 polyfill when necessary.
JavaScript
1
star
44

asset-plugin-experiment

JavaScript
1
star
45

module-property-refined-proposal

Yet another proposal for ES module distinction in Node
1
star
46

esm-resolver-test

JavaScript
1
star
47

amd-version

RequireJS semver-compatible versioning plugin
JavaScript
1
star
48

chrome-modules-bug

ES modules circular test case
JavaScript
1
star
49

separate-css-test

JavaScript
1
star
50

styletab

JavaScript
1
star
51

systemjs-sandbox

Prototype sandbox demo for SystemJS
JavaScript
1
star
52

require-cs

JavaScript
1
star
53

modules-link-preload

Testing link rel=preload for module scripts in browsers
JavaScript
1
star
54

modules-benchmarks

Module loading benchmarks
JavaScript
1
star