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

configuration.mddocs/

Configuration

Brocfile configuration loading and processing functionality. The configuration system loads and executes build definitions from Brocfile.js or Brocfile.ts files.

Capabilities

loadBrocfile Function

Main function for loading and processing Brocfile configuration files.

/**
 * Load and process Brocfile configuration
 * @param options - Optional configuration for loading behavior
 * @returns Function that creates the build tree with environment options
 */
function loadBrocfile(options?: LoadBrocfileOptions): (options: BrocfileOptions) => Node;

interface LoadBrocfileOptions {
  /** Path to the Brocfile (default: searches for Brocfile.js/Brocfile.ts in cwd) */
  brocfilePath?: string;
  
  /** Current working directory (default: process.cwd()) */
  cwd?: string;
}

interface BrocfileOptions {
  /** Environment setting (development/production/test) */
  env: string;
}

Usage Examples:

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

// Load default Brocfile.js from current directory
const buildFn = loadBrocfile();
const tree = buildFn({ env: 'development' });

// Load specific Brocfile
const buildFn2 = loadBrocfile({
  brocfilePath: './config/Brocfile.js',
  cwd: process.cwd()
});
const prodTree = buildFn2({ env: 'production' });

// Load from different working directory
const buildFn3 = loadBrocfile({
  cwd: '/path/to/project'
});
const tree3 = buildFn3({ env: 'development' });

requireBrocfile Function

Lower-level function for requiring a specific Brocfile.

/**
 * Require a specific Brocfile module
 * @param brocfilePath - Path to the Brocfile to require
 * @returns The loaded Brocfile module
 */
function requireBrocfile(brocfilePath: string): any;

Usage Examples:

const { requireBrocfile } = require("broccoli");

// Direct Brocfile loading
const brocfileModule = requireBrocfile('./Brocfile.js');

// Handle different export patterns
let buildFn;
if (typeof brocfileModule === 'function') {
  buildFn = brocfileModule;
} else if (brocfileModule.default) {
  buildFn = brocfileModule.default;
} else {
  throw new Error('Invalid Brocfile format');
}

const tree = buildFn({ env: 'development' });

Brocfile Patterns

JavaScript Brocfile (Brocfile.js)

Standard JavaScript configuration using module.exports.

// Brocfile.js
const { join } = require('path');
const Funnel = require('broccoli-funnel');
const merge = require('broccoli-merge-trees');

module.exports = function(options) {
  const env = options.env || 'development';
  
  // Source files
  const app = new Funnel('app', {
    destDir: '/'
  });
  
  const vendor = new Funnel('vendor', {
    destDir: '/vendor'
  });
  
  // Environment-specific processing
  if (env === 'production') {
    const UglifyJS = require('broccoli-uglify-js');
    app = new UglifyJS(app);
  }
  
  return merge([app, vendor]);
};

ES Modules Brocfile (Brocfile.js with type: "module")

Modern ES modules syntax for Brocfile.

// Brocfile.js (with "type": "module" in package.json)
const { join } from 'path';
import Funnel from 'broccoli-funnel';
import merge from 'broccoli-merge-trees';

export default function(options) {
  const env = options.env || 'development';
  
  let app = new Funnel('src', {
    include: ['**/*.js'],
    destDir: '/'
  });
  
  const assets = new Funnel('public', {
    destDir: '/assets'
  });
  
  if (env === 'production') {
    const { minify } = await import('broccoli-terser');
    app = minify(app);
  }
  
  return merge([app, assets]);
}

TypeScript Brocfile (Brocfile.ts)

TypeScript configuration with full type safety.

// Brocfile.ts
const { join } from 'path';
import Funnel from 'broccoli-funnel';
import merge from 'broccoli-merge-trees';
const { BrocfileOptions } from 'broccoli';

export default function(options: BrocfileOptions): Node {
  const env = options.env || 'development';
  
  // TypeScript compilation
  const typescript = require('broccoli-typescript-compiler');
  
  let app = typescript('src', {
    tsconfig: {
      compilerOptions: {
        target: 'es2018',
        module: 'es2015',
        moduleResolution: 'node'
      }
    }
  });
  
  // Environment-specific optimizations
  if (env === 'production') {
    const uglify = require('broccoli-uglify-js');
    app = uglify(app, {
      compress: true,
      mangle: true
    });
  }
  
  const assets = new Funnel('assets', {
    destDir: '/assets'
  });
  
  return merge([app, assets], {
    overwrite: true
  });
}

Dynamic Configuration

Configuration that adapts based on environment and conditions.

// Brocfile.js - Dynamic configuration
const { existsSync } = require('fs');
const { join } = require('path');

module.exports = function(options) {
  const env = options.env || 'development';
  const isDev = env === 'development';
  const isProd = env === 'production';
  const isTest = env === 'test';
  
  // Base configuration
  const config = {
    minification: isProd,
    sourceMaps: isDev,
    linting: isDev || isTest,
    typeChecking: !isTest
  };
  
  // Load environment-specific overrides
  const envConfigPath = join(__dirname, `config/${env}.js`);
  if (existsSync(envConfigPath)) {
    const envConfig = require(envConfigPath);
    Object.assign(config, envConfig);
  }
  
  // Build tree based on configuration
  let app = require('./lib/build-app')(config);
  
  if (config.linting) {
    const ESLint = require('broccoli-eslint');
    app = new ESLint(app);
  }
  
  if (config.typeChecking) {
    const TypeScript = require('broccoli-typescript-compiler');
    app = new TypeScript(app);
  }
  
  if (config.minification) {
    const UglifyJS = require('broccoli-uglify-js');
    app = new UglifyJS(app);
  }
  
  return app;
};

Multi-Environment Configuration

Comprehensive configuration supporting multiple environments.

// Brocfile.js - Multi-environment
const merge = require('broccoli-merge-trees');
const Funnel = require('broccoli-funnel');

module.exports = function(options) {
  const env = options.env || 'development';
  
  // Common base tree
  const app = new Funnel('app', {
    exclude: ['**/*.test.js']
  });
  
  const environments = {
    development: () => {
      // Development-specific setup
      const LiveReload = require('broccoli-livereload');
      const app = new Funnel('app');
      
      return new LiveReload(app, {
        target: 'index.html'
      });
    },
    
    production: () => {
      // Production optimizations
      const UglifyJS = require('broccoli-uglify-js');
      const CleanCSS = require('broccoli-clean-css');
      
      let js = new Funnel(app, {
        include: ['**/*.js']
      });
      js = new UglifyJS(js);
      
      let css = new Funnel(app, {
        include: ['**/*.css']
      });
      css = new CleanCSS(css);
      
      return merge([js, css]);
    },
    
    test: () => {
      // Test environment setup
      const tests = new Funnel('tests', {
        destDir: '/tests'
      });
      
      return merge([app, tests]);
    }
  };
  
  const buildFn = environments[env];
  if (!buildFn) {
    throw new Error(`Unknown environment: ${env}`);
  }
  
  return buildFn();
};

Configuration Validation

Validate and provide defaults for configuration options.

// Brocfile.js - With validation
module.exports = function(options) {
  // Validate options
  if (!options || typeof options !== 'object') {
    throw new Error('Brocfile options must be an object');
  }
  
  // Provide defaults
  const config = {
    env: 'development',
    outputPath: 'dist',
    minify: false,
    sourceMaps: true,
    ...options
  };
  
  // Validate environment
  const validEnvs = ['development', 'production', 'test'];
  if (!validEnvs.includes(config.env)) {
    throw new Error(`Invalid environment: ${config.env}. Must be one of: ${validEnvs.join(', ')}`);
  }
  
  // Environment-specific defaults
  if (config.env === 'production') {
    config.minify = config.minify !== false;
    config.sourceMaps = config.sourceMaps === true;
  }
  
  console.log(`Building for ${config.env} environment`);
  console.log(`Configuration:`, config);
  
  // Build based on validated config
  return buildTree(config);
};

function buildTree(config) {
  // Implementation based on config
  const Funnel = require('broccoli-funnel');
  let tree = new Funnel('src');
  
  if (config.minify) {
    const UglifyJS = require('broccoli-uglify-js');
    tree = new UglifyJS(tree);
  }
  
  return tree;
}

Error Handling in Brocfiles

Proper error handling and reporting in configuration files.

// Brocfile.js - Error handling
module.exports = function(options) {
  try {
    const env = options.env || 'development';
    
    // Validate required dependencies
    const requiredPlugins = [
      'broccoli-funnel',
      'broccoli-merge-trees'
    ];
    
    for (const plugin of requiredPlugins) {
      try {
        require.resolve(plugin);
      } catch (error) {
        throw new Error(`Required plugin not found: ${plugin}. Run: npm install --save-dev ${plugin}`);
      }
    }
    
    // Build tree with error handling
    return buildTree(env);
    
  } catch (error) {
    console.error('Brocfile configuration error:', error.message);
    throw error;
  }
};

function buildTree(env) {
  const Funnel = require('broccoli-funnel');
  const merge = require('broccoli-merge-trees');
  
  try {
    const app = new Funnel('app');
    const vendor = new Funnel('vendor');
    
    return merge([app, vendor]);
  } catch (error) {
    throw new Error(`Failed to build tree: ${error.message}`);
  }
}