Skip to content

feat(edge-bundler): exclude unrouted functions from the bundle - #7132

Merged
pieh merged 2 commits into
mainfrom
jake/ef-exclude-uncofigured
Jul 24, 2026
Merged

feat(edge-bundler): exclude unrouted functions from the bundle#7132
pieh merged 2 commits into
mainfrom
jake/ef-exclude-uncofigured

Conversation

@JakeChampion

Copy link
Copy Markdown
Contributor

Summary

Functions with no route are never invoked, but they were still bundled and eagerly loaded, which could surface import-time failures Behind the edge_bundler_exclude_unrouted_functions flag, compute routes before bundling and leave unrouted functions out of the tarball and ESZIP

https://linear.app/netlify/issue/FRB-2238/exclude-unconfigured-edge-functions-from-nimble-bundles

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds the edge_bundler_exclude_unrouted_functions flag. When enabled, manifest routes are computed before packaging and unrouted functions are excluded from tarball and ESZIP bundles. Empty bundle output creates the manifest directory and skips ESZIP generation. Tests cover routed and unrouted cases, updated error snapshots, dry-run paths, and the NPM scheme fixture.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: excluding unrouted edge functions from bundles.
Description check ✅ Passed The summary and motivation are clear and aligned with the change, and it includes the related issue link.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jake/ef-exclude-uncofigured

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

e18e dependency analysis

No dependency warnings found.

@pkg-pr-new

pkg-pr-new Bot commented Jul 20, 2026

Copy link
Copy Markdown

Open in StackBlitz

@netlify/build

npm i https://pkg.pr.new/@netlify/build@7132

@netlify/build-info

npm i https://pkg.pr.new/@netlify/build-info@7132

@netlify/cache-utils

npm i https://pkg.pr.new/@netlify/cache-utils@7132

@netlify/config

npm i https://pkg.pr.new/@netlify/config@7132

@netlify/edge-bundler

npm i https://pkg.pr.new/@netlify/edge-bundler@7132

@netlify/functions-utils

npm i https://pkg.pr.new/@netlify/functions-utils@7132

@netlify/git-utils

npm i https://pkg.pr.new/@netlify/git-utils@7132

@netlify/headers-parser

npm i https://pkg.pr.new/@netlify/headers-parser@7132

@netlify/api

npm i https://pkg.pr.new/@netlify/api@7132

@netlify/nock-udp

npm i https://pkg.pr.new/@netlify/nock-udp@7132

@netlify/opentelemetry-sdk-setup

npm i https://pkg.pr.new/@netlify/opentelemetry-sdk-setup@7132

@netlify/opentelemetry-utils

npm i https://pkg.pr.new/@netlify/opentelemetry-utils@7132

@netlify/redirect-parser

npm i https://pkg.pr.new/@netlify/redirect-parser@7132

@netlify/run-utils

npm i https://pkg.pr.new/@netlify/run-utils@7132

@netlify/zip-it-and-ship-it

npm i https://pkg.pr.new/@netlify/zip-it-and-ship-it@7132

commit: d248d31

@JakeChampion
JakeChampion force-pushed the jake/ef-exclude-uncofigured branch from 72a41e3 to 361909f Compare July 20, 2026 09:27
@JakeChampion
JakeChampion marked this pull request as ready for review July 20, 2026 09:41
@JakeChampion
JakeChampion requested a review from a team as a code owner July 20, 2026 09:41
@JakeChampion
JakeChampion requested a review from pieh July 20, 2026 09:41
Comment thread packages/edge-bundler/node/bundler.ts
Comment thread packages/edge-bundler/node/bundler.ts Outdated
Comment thread packages/edge-bundler/node/bundler.ts
@JakeChampion
JakeChampion force-pushed the jake/ef-exclude-uncofigured branch from 361909f to 25eac21 Compare July 21, 2026 10:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/build/tests/edge_functions/snapshots/tests.js.md`:
- Around line 1315-1319: Update the stderr snapshot string in the affected test
fixture to use escaped newline characters (\n) rather than literal /n sequences,
including the separator before the source excerpt and its subsequent lines.
Preserve the existing error text and formatting so it matches the actual
multiline stderr output.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bf093cd8-0406-4d0e-981c-d4d750539418

📥 Commits

Reviewing files that changed from the base of the PR and between 9b53db7 and 9ccfddc.

⛔ Files ignored due to path filters (1)
  • packages/build/tests/edge_functions/snapshots/tests.js.snap is excluded by !**/*.snap
📒 Files selected for processing (1)
  • packages/build/tests/edge_functions/snapshots/tests.js.md
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • netlify/blueprints (manual)

Comment thread packages/build/tests/edge_functions/snapshots/tests.js.md Outdated
@JakeChampion
JakeChampion requested a review from pieh July 22, 2026 09:55
@JakeChampion
JakeChampion enabled auto-merge (squash) July 22, 2026 09:55

await vendor?.cleanup()

return { functions, manifest: undefined }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is correct thing to do, just noting that it changes signature of this function and it is exported from @netlify/edge-bundler -

export { bundle } from './bundler.js'

before (i.e. https://npmx.dev/package-code/@netlify/edge-bundler/v/15.1.1/dist%2Fnode%2Fbundler.d.ts#L23-L26):

export declare const bundle: (sourceDirectories: string[], distDirectory: string, tomlDeclarations?: Declaration[], { basePath: inputBasePath, cacheDirectory, configPath, debug, distImportMapPath, featureFlags: inputFeatureFlags, importMapPaths, internalSrcFolder, onAfterDownload, onBeforeDownload, rootPath, userLogger, systemLogger, vendorDirectory, }?: BundleOptions) => Promise<{
    functions: EdgeFunction[];
    manifest: import("./manifest.js").Manifest;
}>;

after:

export declare const bundle: (sourceDirectories: string[], distDirectory: string, tomlDeclarations?: Declaration[], { basePath: inputBasePath, cacheDirectory, configPath, debug, distImportMapPath, featureFlags: inputFeatureFlags, importMapPaths, internalSrcFolder, onAfterDownload, onBeforeDownload, rootPath, userLogger, systemLogger, vendorDirectory, }?: BundleOptions) => Promise<{
    functions: EdgeFunction[];
    manifest: undefined;
} | {
    functions: EdgeFunction[];
    manifest: import("./manifest.js").Manifest;
}>;

I think this warrants major version bump for @netlify/edge-bundler just to be safe. As far as I'm aware @netlify/build is only consumer of it, but I'm not 100% sure on this.

The annoying part here is that I'm not sure if release-please have a way to only bump major for just @netlify/edge-bundler without bumping it also for @netlify/build which does NOT need major bump. I'll try to figure this out without doing some weird PR splits so release-please is satisfied.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pieh if we didn't do a merge commit or squash merge, then it work because each commit can have a different feat/fix etc

@JakeChampion
JakeChampion disabled auto-merge July 22, 2026 12:21
Comment on lines 82 to 92
logFunctionsToBundle({
logs,
userFunctions: userFunctions.map(({ name }) => name),
userFunctionsSrc: srcDirectory,
userFunctionsSrcExists,
internalFunctions: internalFunctions.map(({ name }) => name),
internalFunctionsSrc: internalSrcDirectory,
frameworkFunctions: frameworkFunctions.map(({ name }) => name),
type: 'Edge Functions',
generatedFunctions: {},
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not blocking (IMO), just something that noticed when testing this change that seems worth enough to mention

In case I have no routable EF I do get those logs

Edge Functions bundling                                       
────────────────────────────────────────────────────────────────

Packaging Edge Functions from netlify/edge-functions directory:
 - wat

(Edge Functions bundling completed in 1.6s)

Without getting feedback that this particular EF was not actually "packaged".

I don't think this is exactly a regression in practice even if "technically" it might be considered one, because today if the EF is not routable - while EF is packaged - but's never invokable, so in practice wether EF was packaged or skipped doesn't seem to matter in practice - in both cases it just will never run.

We maybe could use this opportunity to add a note/warning mentioning that EF does not have any routes and it will never be invoked and have call to action for user to either add routing OR if the module was listed here but is not meant to be actual EF - do something to not be considered EF candidate (this is part is main reason to not even try to do that in this PR because when I was looking for our documentation - the logic used to determine what files should be considered edge functions https://github.com/netlify/build/blob/main/packages/edge-bundler/node/finder.ts doesn't seem to be properly documented so we could not refer to documentation even if we wanted to without adding a section about it first)

@pieh
pieh force-pushed the jake/ef-exclude-uncofigured branch from e14f077 to 5322d53 Compare July 23, 2026 16:32
A function with no route can never be invoked, so bundling it only
eagerly loads code that can never run, which can surface import-time
failures for functions that are not even in use. Behind the
`edge_bundler_exclude_unrouted_functions` feature flag, unrouted
functions are left out of the bundle, and when nothing is left to bundle
we produce neither a bundle nor a manifest.

BREAKING CHANGE: the `manifest` property returned by `bundle` is now
`Manifest | undefined`. It is `undefined` when no function is bundled.
@pieh
pieh merged commit 8140b96 into main Jul 24, 2026
110 of 113 checks passed
@pieh
pieh deleted the jake/ef-exclude-uncofigured branch July 24, 2026 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants