Skip to content

A build tool for apps and packages, static and server-rendered sites

Notifications You must be signed in to change notification settings

seek-oss/crackle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

💥 Crackle

A build tool for apps and packages, static and server-rendered sites. Built on Vite, Rollup and esbuild.

Features

Contents

Getting started

pnpm add --save-dev @crackle/cli

Crackle will look for a crackle.config.ts file in the project directory, but if one doesn't exist, it will use the default configuration.

Here's how to specify a custom configuration file:

// crackle.config.ts
import { defineConfig } from '@crackle/cli/config';

export default defineConfig({
  // ...
});

or

// crackle.config.ts
import type { UserConfig } from '@crackle/cli/config';

export default {
  // ...
} satisfies UserConfig;

(the default config values are documented in the type UserConfig)

Commands

You can find the full list of commands by running crackle --help.

The most common ones are listed below.

crackle package

Compile the package for publishing. This will compile TypeScript files to CJS- and ESM-compatible files and generate TypeScript declaration files (.d.ts files) for entry points. Passing the --fix parameter will also run crackle fix.

The default entry point is src/index.ts. Multiple (nested) entry points are supported, by adding .ts files to src/entries/.

Entry points

Given this directory structure:

src
├── entries
│   ├── components.ts
│   └── themes
│       └── apac.ts
└── index.ts

Crackle will generate these entry points:

my-project (main entry point; mapped to src/index.ts)
my-project/components (mapped to src/entries/components.ts)
my-project/themes/apac (mapped to src/entries/themes/apac.ts)

Externals

If a dependency is present in devDependencies (but not in peerDependencies) it is bundled along with the project's source code. dependencies, peerDependencies and optionalDependencies are marked as external and not bundled.

Package mode

crackle package --mode=bundle
crackle package --mode=preserve

This controls how Crackle generates output files.

  • bundle rolls up output files into as few chunks as possible (default behaviour)
  • preserve creates separate files for all modules using the original module names as file names. This is similar to Rollup's output.preserveModules, but allows more fine-grained control because we hook into output.manualChunks.

The mode can also be configured via crackle.config.ts:

// crackle.config.ts
import { defineConfig } from '@crackle/cli/config';

export default defineConfig({
  package: {
    mode: 'preserve',
  },
});

DTS mode

Some libraries declare namespaces, which are hard/impossible to bundle. For such cases, Crackle has an option to preserve the file structure of the generated .d.ts files.

// crackle.config.ts
import { defineConfig } from '@crackle/cli/config';

export default defineConfig({
  dts: {
    mode: 'preserve',
  },
});
  • bundle rolls up output files into as few chunks as possible (default behaviour)
  • preserve creates separate files for all modules using the original module names as file names. This is similar to Rollup's output.preserveModules.

crackle dev

Generate entry points for local development. This will generate stub entry points for local development. Stub entry points import the source files directly instead of the compiled files.

Shim mode

By default, Crackle generates a require shim which enables the loading of TypeScript files in Node.js using a require hook. There are situations where this is not required, such as when using a bundler that supports TypeScript natively, e.g. esbuild or Vite. In these cases, the --shim option can be set to none.

crackle dev --shim=require
crackle dev --shim=none
  • require generates a shim for use in Node.js (default behaviour)
  • none doesn't generate a require shim

This can also be configured via crackle.config.ts:

// crackle.config.ts
import { defineConfig } from '@crackle/cli/config';

export default defineConfig({
  dev: {
    shim: 'none',
  },
});

crackle fix

Updates package.json exports, files, sideEffects field and more:

  • package.json: "main", "module" and "types" are updated to point to the generated files in dist
  • package.json: "exports" and "files" are updated to include generated entry points
  • package.json: "sideEffects" flag is updated to match the generated files in dist
  • package.json: keys are sorted using sort-package-json
  • .gitignore is updated to ignore backwards-compatible entry points

Side-effects

Crackle updates the sideEffects flag if needed. If an entry point has side-effects (as defined via package.json's "sideEffects" key), Crackle will update the "sideEffects" key to match the output path in dist.

Based on what's in src and the value of the flag, when running crackle package these things will happen:

  • .css.ts files (and files importing them) will be placed in dist/styles/<same-path-as-in-src>
  • files with side-effects (matching the globs defined in "sideEffects") will be placed in dist/side-effects/<same-path-as-in-src>
  • if an entry has side-effects, the "sideEffects" key will be updated to match the output path in dist

ESM reconciliation

In the ESM build, Crackle will automatically reconcile import specifiers in the output code to point to an actual file when the imported package doesn't have an "exports" field.

More details in ESM reconciliation.

DTS bundles

Crackle will generate type declaration files (.d.ts) for entry points. The same rules for dependencies apply here, meaning types for devDependencies (but not peerDependencies) are bundled with the project's types.

Backwards-compatible entry points

Crackle generates backwards-compatible entry points for tools which don't support the "exports" field in package.json. Although there is good support in bundlers and Node.js, there are still some tools that don't support it, mainly TypeScript versions below 5.0.

Contributing

  • Clone this repository
  • Set up Node.js using Volta
  • Enable Corepack using corepack enable
  • Install dependencies using pnpm install
  • Run bootstrap script using pnpm bootstrap
  • Run pnpm dev which runs crackle dev in every package or run pnpm build to build packages using crackle package

Self-hosting / Bootstrap

Crackle is self-hosting: it is built and tested with itself. There's a bootstrap package that uses a published version of Crackle to build the packages in the monorepo. This is done by running pnpm bootstrap at the root of the monorepo.

Once the bootstrap script is done, the current version of Crackle can be used to build itself. If anything goes wrong and the bootstrap script fails, there's a fallback script to build @crackle/core using unbuild by running pnpm unbuild in the packages/core directory.