better-firebase-functions-esbuild
raw JSON → 7.1.1 verified Fri May 01 auth: no javascript
esbuild plugin for optimizing Firebase Cloud Functions builds. Version 7.1.1 is the latest stable, released April 2026, requiring Node >=20 and esbuild >=0.17.0. It provides per-function entry point generation with tree shaking by executing the BFF entry point in a discovery mode, automatically reusing runtime config (functionDirectoryPath, searchGlob, etc.) so no duplicate configuration is needed. Published weekly, it supports buildFunctions() as the recommended API, along with manual discovery helpers and a logging plugin. Differentiates from vanilla esbuild by automating the discovery of Firebase function files and maintaining the output directory structure matching the runtime layout.
Common errors
error Error [ERR_REQUIRE_ESM]: require() of ES Module /path/to/node_modules/better-firebase-functions-esbuild/build/index.js from /path/to/your-script.js not supported. ↓
cause Package is ESM-only since v7.0.0, but your project uses CommonJS require().
fix
Switch to import syntax and set "type": "module" in your package.json, or use dynamic import().
error TypeError: bffEsbuildPlugin is not a function ↓
cause Incorrect import: default import attempted but bffEsbuildPlugin is a named export.
fix
Use import { bffEsbuildPlugin } from 'better-firebase-functions-esbuild'.
error Error: No functions discovered. Check your entry point exports functions via exportFunctions/exportFunctionsAsync. ↓
cause Entry point does not call exportFunctions() or exportFunctionsAsync(), or the glob pattern finds no files.
fix
Ensure your entry point invokes exportFunctions({ ... }) with correct functionDirectoryPath and searchGlob.
Warnings
breaking v6.0.0 dropped support for Node <14, upgraded all dependencies. ↓
fix Upgrade Node to >=14 or use v5.0.0 if stuck on older Node.
breaking v7.0.0 switched to ESM-only; CommonJS require() no longer works. ↓
fix Migrate your project to ESM (type: module in package.json) and use import syntax.
gotcha bffEsbuildPlugin() cannot add entry points dynamically; it only logs. Use buildFunctions() for actual bundling. ↓
fix Use buildFunctions() instead of the plugin for per-function output.
gotcha If your entry point exports functions using exportFunctions(), you must provide the config at runtime; the plugin executes the entry point in discovery mode, so any external side effects may run twice. ↓
fix Wrap side effects in guards that skip during discovery mode (check process.env.BFF_DISCOVERY).
Install
npm install better-firebase-functions-esbuild yarn add better-firebase-functions-esbuild pnpm add better-firebase-functions-esbuild Imports
- buildFunctions wrong
const buildFunctions = require('better-firebase-functions-esbuild')correctimport { buildFunctions } from 'better-firebase-functions-esbuild' - discoverFunctionEntryPoints wrong
import * as BFF from 'better-firebase-functions-esbuild'; BFF.discoverFunctionEntryPoints()correctimport { discoverFunctionEntryPoints } from 'better-firebase-functions-esbuild' - discoverBuildEntryPoints wrong
import { discoverBuildEntryPoints } from 'better-firebase-functions'correctimport { discoverBuildEntryPoints } from 'better-firebase-functions-esbuild'
Quickstart
import { buildFunctions } from 'better-firebase-functions-esbuild';
import { resolve } from 'path';
// Ensure your entry point exports functions via exportFunctions/exportFunctionsAsync
await buildFunctions({
entryPoint: resolve(__dirname, 'src/index.ts'),
outdir: resolve(__dirname, 'dist'),
target: 'node20',
verbose: true,
});
// Output: dist/main.js and dist/functions/**/*.js mirroring runtime layout