or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

build-system.mdcli.mdconfiguration.mddev-server.mderror-handling.mdfile-watching.mdindex.md
tile.json

tessl/npm-broccoli

Fast client-side asset builder with plugin-based architecture for transforming files and directories

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/broccoli@3.5.x

To install, run

npx @tessl/cli install tessl/npm-broccoli@3.5.0

index.mddocs/

Broccoli

Broccoli is a fast, reliable asset pipeline and build tool for frontend development, supporting constant-time rebuilds and compact build definitions. It provides a plugin-based architecture for transforming files and directories, with support for TypeScript compilation, asset processing, and live reloading during development.

Package Information

  • Package Name: broccoli
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install --save-dev broccoli + npm install --global broccoli-cli

Core Imports

Broccoli uses CommonJS exports exclusively:

const broccoli = require("broccoli");

// Access main components
const Builder = broccoli.Builder;
const Watcher = broccoli.Watcher;
const WatcherAdapter = broccoli.WatcherAdapter;
const loadBrocfile = broccoli.loadBrocfile;
const getMiddleware = broccoli.getMiddleware;
const cli = broccoli.cli;

// Server functionality requires separate destructuring
const { Server, serve } = broccoli.server;

Destructured imports:

const { Builder, Watcher, loadBrocfile, getMiddleware, cli } = require("broccoli");
const { serve } = require("broccoli").server;

Basic Usage

const { Builder, loadBrocfile } = require("broccoli");

// Load Brocfile configuration
const buildFn = loadBrocfile({ 
  brocfilePath: './Brocfile.js',
  cwd: process.cwd()
});

// Create build tree from Brocfile
const tree = buildFn({ env: 'development' });

// Create and run builder
const builder = new Builder(tree);
await builder.build();
console.log('Build output at:', builder.outputPath);
await builder.cleanup();

Development server with file watching:

const { Builder, Watcher, loadBrocfile } = require("broccoli");
const { serve } = require("broccoli").server;

const buildFn = loadBrocfile();
const tree = buildFn({ env: 'development' });
const builder = new Builder(tree);

// Start file watcher
const watcher = new Watcher(builder, builder.watchedSourceNodeWrappers);
await watcher.start();

// Start development server
await serve(watcher, 'localhost', '4200', undefined, undefined, undefined, false, '', '');

Architecture

Broccoli is built around several key components:

  • Build Graph: Tree-based structure where each transformation creates a new tree
  • Node System: Wrapper classes (SourceNodeWrapper, TransformNodeWrapper) for build graph nodes
  • Builder: Core orchestration engine that manages the build process
  • Watcher: File system monitoring for incremental rebuilds
  • Server: Development server with live reloading capabilities
  • Plugin API: Extensible transformation pipeline through broccoli plugins

Capabilities

Build Orchestration

Core build functionality for executing transformation pipelines and managing build state.

class Builder {
  constructor(outputNode: Node, options?: BuilderOptions);
  
  readonly outputNode: Node;
  readonly outputPath: string;
  readonly buildId: number;
  readonly watchedPaths: string[];
  readonly unwatchedPaths: string[];
  readonly watchedSourceNodeWrappers: SourceNodeWrapper[];
  
  build(): Promise<void>;
  cancel(): Promise<void>;
  cleanup(): Promise<void>;
  makeNodeWrapper(node: Node, _stack?: any): NodeWrapper;
}

interface BuilderOptions {
  tmpdir?: string | null;
}

// Static error classes available on Builder
Builder.BuilderError: typeof BuilderError;
Builder.InvalidNodeError: typeof InvalidNodeError;
Builder.NodeSetupError: typeof NodeSetupError;
Builder.BuildError: typeof BuildError;
Builder.NodeWrapper: typeof NodeWrapper;
Builder.TransformNodeWrapper: typeof TransformNodeWrapper;
Builder.SourceNodeWrapper: typeof SourceNodeWrapper;

Build System

File Watching

File system monitoring and incremental rebuild capabilities for development workflows.

class Watcher extends EventEmitter {
  constructor(
    builder: any, 
    watchedNodes: SourceNodeWrapper[], 
    options?: WatcherOptions
  );
  
  readonly currentBuild: Promise<void>;
  readonly builder: any;
  
  start(): Promise<void>;
  quit(): Promise<void>;
}

interface WatcherOptions {
  debounce?: number;
  watcherAdapter?: WatcherAdapter;
  saneOptions?: any;
  ignored?: string[];
}

// Events emitted by Watcher:
// 'buildStart' - When a build starts
// 'buildSuccess' - When a build succeeds  
// 'buildFailure' - When a build fails with error
// 'change' - When files change
// 'debounce' - During debounce period
// 'quitStart', 'quitEnd' - During shutdown

File Watching

Development Server

HTTP server for serving built assets during development with live reloading support.

// Server module exports: { Server, serve }
const { Server, serve } = require("broccoli").server;

class Server {
  constructor(
    watcher: Watcher,
    host: string,
    port: string,
    connect?: any,
    ui?: UI,
    ssl?: boolean,
    sslKey?: string,
    sslCert?: string
  );
  
  start(): Promise<void>;
  stop(): Promise<void>;
}

function serve(
  watcher: Watcher,
  host: string,
  port: string,
  _connect?: any,
  _process?: any,
  ui?: UI,
  ssl?: boolean,
  sslKey?: string,
  sslCert?: string
): Promise<void>;

function getMiddleware(
  watcher: Watcher, 
  options?: MiddlewareOptions
): (req: any, res: any, next: any) => any;

interface MiddlewareOptions {
  autoIndex?: boolean;
  liveReloadPath?: string;
}

Development Server

Configuration Loading

Brocfile configuration loading and processing functionality.

function loadBrocfile(options?: LoadBrocfileOptions): (options: BrocfileOptions) => Node;

interface LoadBrocfileOptions {
  brocfilePath?: string;
  cwd?: string;
}

interface BrocfileOptions {
  env: string; // Default: 'development'
}

Configuration

Command Line Interface

Complete CLI implementation for build, serve, and other commands.

function cli(args: string[], ui?: UI): Promise<any>;

Command Line Interface

Low-Level File Watching

Low-level file system monitoring using the sane package for custom watching implementations.

class WatcherAdapter extends EventEmitter {
  constructor(
    watchedNodes: SourceNodeWrapper[],
    options?: any,
    ignored?: string[]
  );
  
  watch(): Promise<void>;
  quit(): Promise<void>;
}

// Events emitted by WatcherAdapter:
// 'change' - File change events
// 'error' - Watch errors

Error Handling

Comprehensive error system for build failures, node setup issues, and cancellation.

// Error classes accessed via Builder static properties
const BuilderError = Builder.BuilderError;
const BuildError = Builder.BuildError;
const NodeSetupError = Builder.NodeSetupError;
const InvalidNodeError = Builder.InvalidNodeError;

class BuilderError extends Error {
  readonly isBuilderError: boolean;
  constructor(message?: string);
  static isBuilderError(error: any): boolean;
}

class BuildError extends BuilderError {
  readonly isSilent: boolean;
  readonly isCancellation: boolean;
  readonly broccoliPayload: BroccoliPayloadError;
  constructor(originalError: any, nodeWrapper?: NodeWrapper);
}

class NodeSetupError extends BuilderError {
  constructor(originalError: Error, nodeWrapper?: NodeWrapper);
}

class InvalidNodeError extends BuilderError {
  constructor(message?: string);
}

class Cancelation extends Error {
  readonly isCancelation: boolean;
  readonly isSilent: boolean;
  constructor(message?: string);
  static isCancelationError(e: any): boolean;
}

interface BroccoliPayloadError {
  originalError: Error;
  originalMessage: string;
  nodeId: number;
  nodeLabel: string;
  nodeName: string;
  nodeAnnotation: string | undefined | null;
  instantiationStack: string;
  location: {
    file: string;
    treeDir: string;
    line: number;
    column: number;
  };
}

Error Handling

Types

interface Node {
  // Broccoli plugin node interface
  [key: string]: any;
}

// Node wrapper classes (available via Builder static properties)
class NodeWrapper {
  readonly id: number;
  readonly label: string;
  readonly cachePath: string;
  readonly outputPath: string;
  readonly nodeInfo: any;
  readonly inputNodeWrappers: NodeWrapper[];
  readonly buildState: {
    selfTime?: number;
    totalTime?: number;
    built?: boolean;
  };
  
  constructor();
  build(): void | Promise<void>;
  revise(): void;
  get revision(): number;
  toString(): string;
  toJSON(): object;
  formatInstantiationStackForTerminal(): string;
  nodeInfoToJSON(): object;
}

class SourceNodeWrapper extends NodeWrapper {
  setup(features: any): void;
  build(): void;
  toString(): string;
  nodeInfoToJSON(): object;
}

class TransformNodeWrapper extends NodeWrapper {
  readonly inputRevisions: WeakMap<any, { revision: number; changed: boolean }>;
  readonly callbackObject: any;
  readonly inputPaths: string[];
  
  setup(features: any): void;
  shouldBuild(): boolean;
  build(): Promise<void>;
  toString(): string;
  nodeInfoToJSON(): object;
}

interface UI {
  write(message: string, writeLevel?: string): void;
  writeLine(message: string, writeLevel?: string): void;
  writeError(error: Error): void;
}