Brocfile configuration loading and processing functionality. The configuration system loads and executes build definitions from Brocfile.js or Brocfile.ts files.
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' });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' });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]);
};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 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
});
}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;
};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();
};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;
}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}`);
}
}