npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

better-firebase-functions-esbuild

v7.1.1

Published

esbuild plugin for optimized Firebase Cloud Functions builds. Per-function entry points with tree shaking.

Readme

better-firebase-functions-esbuild

esbuild helper/plugin for better-firebase-functions.

This package discovers your Firebase function files using the same config already present in your BFF entry point, then builds one bundled output file per function.

Install

npm install -D better-firebase-functions-esbuild esbuild

How discovery works

The plugin executes your entry point in a special BFF build-discovery mode. That means it reuses the exact runtime config already passed to exportFunctions() or exportFunctionsAsync():

  • functionDirectoryPath
  • searchGlob
  • funcNameFromRelPath
  • __dirname

In the common case you only provide entryPoint to the build helper. No duplicated glob config is required.

Recommended usage: buildFunctions()

Keep your runtime config in the entry point:

// src/index.ts
import { exportFunctions } from 'better-firebase-functions';

exportFunctions({
  __filename,
  exports,
  functionDirectoryPath: './functions',
  searchGlob: '**/*.func.js',
});

Then build with esbuild:

import { buildFunctions } from 'better-firebase-functions-esbuild';
import { resolve } from 'path';

await buildFunctions({
  entryPoint: resolve(__dirname, 'src/index.ts'),
  outdir: resolve(__dirname, 'dist'),
  target: 'node20',
  verbose: true,
});

Output layout

If the source trigger is:

src/functions/auth/on-create.func.ts

...the bundled output will be:

dist/main.js
dist/functions/auth/on-create.func.js

The runtime layout is preserved, so main.js can keep using the same functionDirectoryPath and searchGlob you configured in the entry point.

Manual discovery helpers

discoverFunctionEntryPoints()

Returns a runtime-oriented map of { functionName: absoluteSourcePath }.

import { discoverFunctionEntryPoints } from 'better-firebase-functions-esbuild';

const entryPoints = await discoverFunctionEntryPoints({
  entryPoint: resolve(__dirname, 'src/index.ts'),
});

discoverBuildEntryPoints()

Returns build-ready esbuild entry points whose output paths already mirror the runtime BFF layout.

import { discoverBuildEntryPoints } from 'better-firebase-functions-esbuild';

const { entryPoints, discovery } = await discoverBuildEntryPoints({
  entryPoint: resolve(__dirname, 'src/index.ts'),
});

await esbuild.build({
  entryPoints: {
    main: resolve(__dirname, 'src/index.ts'),
    ...entryPoints,
  },
  outdir: 'dist',
  bundle: true,
  platform: 'node',
  format: 'cjs',
});

Logging plugin: bffEsbuildPlugin()

esbuild's plugin API cannot add entry points dynamically, so the plugin only logs discovery information. Use buildFunctions() for actual per-function bundling.

import { build } from 'esbuild';
import { bffEsbuildPlugin } from 'better-firebase-functions-esbuild';

await build({
  entryPoints: { main: 'src/index.ts' },
  outdir: 'dist',
  bundle: true,
  platform: 'node',
  plugins: [
    bffEsbuildPlugin({
      entryPoint: resolve(__dirname, 'src/index.ts'),
      verbose: true,
    }),
  ],
});

Fallback manual overrides

If your entry point cannot be executed directly during the build, you can still pass discovery overrides manually:

await buildFunctions({
  entryPoint: resolve(__dirname, 'src/index.ts'),
  functionDirectoryPath: './functions',
  searchGlob: '**/*.func.js',
  funcNameFromRelPath: myCustomNameGenerator,
  outdir: 'dist',
});

These overrides are a fallback only. The preferred approach is keeping the discovery config in the entry point and letting the plugin load it automatically.

Notes

  • Your searchGlob should describe runtime files, usually compiled .js files.
  • During build-discovery, BFF automatically expands .js / .cjs / .mjs globs to match source .ts / .cts / .mts files too.
  • If you use a custom funcNameFromRelPath, esbuild discovery reuses it automatically because it is loaded from the entry point itself.