CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-broccoli

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

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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;
}
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/broccoli@3.5.x
Publish Source
CLI
Badge
tessl/npm-broccoli badge