Skip to content

Next.js: freeze the env into the build only when asked or where it's needed - #1232

Merged
theoephraim merged 9 commits into
mainfrom
nextjs-freeze-into-bundle
Oct 19, 2026
Merged

theoephraim merged 9 commits into
mainfrom
nextjs-freeze-into-bundle

Conversation

@theoephraim

@theoephraim theoephraim commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

The Next.js integration baked the fully resolved env (secrets included) into every production build, regardless of host. A standalone server with no varlock CLI then silently booted from build-time values and ignored the runtime env. The docs already said baking only happened on Vercel/OpenNext.

This is the Next.js half of the freeze plan: one decision, made at build, never at boot.

@varlock/nextjs-integration (major)

  • New freezeIntoBundle option: 'auto' (default) freezes on Vercel, Netlify, Cloudflare Workers Builds, AWS Amplify and OpenNext builds; true always; false never. Non-frozen builds bake nothing.
  • output: 'standalone' with 'auto' on an undetected host fails the build until true or false is set, so Docker users hit this in CI rather than at deploy.
  • Frozen builds:
    • must be encrypted (_VARLOCK_ENV_KEY, opt out with _VARLOCK_ALLOW_PLAINTEXT_FROZEN_ENV=1)
    • win over the env at boot (warning on conflicts and on an ignored ambient __VARLOCK_ENV)
    • support @dynamic=boot
    • are announced in the build output
  • The frozen env is also recorded in the next config (required-server-files.json), so the server process boots from it before next.config runs. This applies to the standalone server, next start, and custom servers, never to a build or its workers. The config plugin then checks that the boot came from the build being served: a frozen build in a custom distDir under next start, or a stale frozen .next, fails at boot.
  • During next build itself, prerendering keeps the build's own resolution, so required @dynamic=boot keys with no build-time value don't fail the build.
  • A non-frozen server that can't reach the CLI exits at boot with the fixes, instead of falling back to build-time values.
  • Removed the dead writeResolvedEnvFile.

varlock (minor)

  • varlock load --defer-boot-required: the freeze-time tolerance for required boot items, used by next build.
  • varlock/frozen-env-boot bundle: applies @dynamic=boot values for a frozen env baked into a bundle. It is kept out of the init bundles and varlock/env because it carries the data types (~70KB). node:crypto in data types is now lazy so the bundle loads on edge.
  • initVarlockEnv:
    • warns once when a frozen env conflicts with the env at boot
    • no longer reverts __VARLOCK_ENV to its process-start value on re-init
    • defers when an async edge decrypt is pending (edge-compiled instrumentation.ts)
  • Next's edge sandbox throws on process.getBuiltinModule, so decrypting there now falls back correctly.

Testing

  • Validated before changing anything: on Next 15.5 and 16.4 (webpack and turbopack), self-hosted edge routes and edge middleware inherit the server process env, so non-frozen builds need no bake for edge.
  • Manual matrix: Next 15/16 × webpack/turbopack × {next start, standalone with CLI, standalone without CLI} × {not frozen, frozen}, including a @dynamic=boot key, varlock run on top of a frozen build, and the option variants.
  • Framework tests: encrypted env blob replaced with not-frozen / frozen-on-Vercel / missing-key scenarios. The old assertion only checked for the varlock:v1: prefix, which the runtime code itself contains. The standalone scenarios now cover the build guard, the boot failure, and a frozen boot with a @dynamic=boot override.
  • Vercel deploy suite passes on real deployments (16/16, rerun after the review fixes), both encrypted (frozen with a key) and plaintext (frozen with the opt-out). It covers lambda SSR, Edge middleware, leak detection, and log redaction. The plaintext variant sets _VARLOCK_ALLOW_PLAINTEXT_FROZEN_ENV as project env through the API, like _VARLOCK_ENV_KEY: the Vercel CLI rejects env keys that begin with _.

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

bumpy-frog

The changes in this PR will be included in the next version bump.

major Major releases

  • @varlock/nextjs-integration 1.2.5 → 2.0.0

minor Minor releases

  • @varlock/native-helper-darwin 1.23.0 → 1.24.0
  • @varlock/native-helper-linux-arm64 1.23.0 → 1.24.0
  • @varlock/native-helper-linux-x64 1.23.0 → 1.24.0
  • @varlock/native-helper-win32-x64 1.23.0 → 1.24.0
  • varlock 1.23.0 → 1.24.0

Bump files in this PR

Click here if you want to add another bump file to this PR


This comment is maintained by bumpy.

@github-actions

Copy link
Copy Markdown
Contributor

📦 Bundle size

⚠️ grows the bundle by 99.3 KB (+2.0%)

Metric main This PR Δ
Total dist 5078.8 KB 5178.1 KB +99.3 KB (+2.0%)
JS 1921.7 KB 2000.1 KB +78.5 KB (+4.1%)
Sourcemaps 3026.4 KB 3041.0 KB +14.6 KB (+0.5%)
Type defs 130.7 KB 137.0 KB +6.3 KB (+4.8%)
Other 0.0 KB 0.0 KB —

dist/ only; native binaries are versioned separately and not counted here.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
varlock-website e8a8174 Commit Preview URL

Branch Preview URL
Oct 15 2026, 06:41 AM

@pkg-pr-new

pkg-pr-new Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

varlock

npm i https://pkg.pr.new/varlock@1232

@varlock/nextjs-integration

npm i https://pkg.pr.new/@varlock/nextjs-integration@1232

@varlock/native-helper-darwin

npm i https://pkg.pr.new/@varlock/native-helper-darwin@1232

@varlock/native-helper-linux-arm64

npm i https://pkg.pr.new/@varlock/native-helper-linux-arm64@1232

@varlock/native-helper-linux-x64

npm i https://pkg.pr.new/@varlock/native-helper-linux-x64@1232

@varlock/native-helper-win32-x64

npm i https://pkg.pr.new/@varlock/native-helper-win32-x64@1232

commit: fc76c20

@pullfrog pullfrog 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.

Important

Required boot-only keys still fail during the build, and two production startup paths can resolve fresh values before switching to the frozen env. These need addressing before merge.

Reviewed changes Reviewed the build-time freeze policy, runtime initialization, production boot paths, and associated tests and documentation.

  • Freeze policy: Adds freezeIntoBundle, platform detection, explicit standalone choices, encryption requirements, and shared webpack/Turbopack preludes.
  • Production boot: Records frozen payloads in Next config and loads them before config evaluation, while non-frozen servers require runtime resolution.
  • Boot values: Adds deferred required validation and the varlock/frozen-env-boot bundle, plus frozen conflict warnings and edge decrypt handling.
  • Coverage: Updates framework/deployment tests and hosting docs; the integration build and 59 targeted unit tests passed. An actual Next 15 webpack build reproduced the required boot-key failure below.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

…rvers boot frozen; check the boot source against distDir

@pullfrog pullfrog 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.

Important

No new issues found in these commits. The three unresolved findings from the previous review remain unchanged, so this is not an approval.

Reviewed changes Reviewed the deployment-test fix and encryption-guide updates since 25d4377.

  • Updated deployment setup: Set the plaintext opt-out through Vercel's project-env API, generalized the existing key helpers, and removed per-deployment build-env flags.
  • Clarified encryption setup: Distinguished Next.js frozen builds from Vite injection, documented Vercel project variables, and linked Docker build-secret guidance.

Real Vercel deployments were not rerun in this review.

Pullfrog  | Fix it ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

@pullfrog pullfrog 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.

Important

Production build workers can now boot from a previous frozen build, causing valid rebuilds to fail. The expanded startup detector needs to exclude build execution.

Reviewed changes Reviewed the startup and build-resolution fixes in 62d31b9 since the previous review at e8a8174.

  • Preserved build resolution: Kept the build's existing graph during frozen-runtime execution and added an unset required boot key to the standalone framework fixture.
  • Expanded frozen startup: Included production custom servers in manifest-based initialization before Next config evaluation.
  • Checked build sources: Recorded the boot manifest and rejected frozen custom-directory startup, stale output mismatches, and builds contaminated by earlier frozen output.
  • Verified focused paths: Built the integration and dependencies, passed 27 focused tests, and exercised the compiled loader with custom-server and build-worker environments. Full framework builds and remote deployments were not rerun.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes Reviewed fc76c20 since the prior review at 62d31b9.

  • Excluded build workers: Added inherited-build checks before frozen server detection, preventing workers from loading a previous build's frozen output.
  • Added regression coverage: Tested current-graph preservation with old frozen output present and confirmed production custom servers still boot frozen without invoking the CLI.

The integration and its workspace dependencies built successfully, and all 30 focused tests passed. Full Next.js framework builds and remote deployments were not rerun.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@theoephraim
theoephraim merged commit 8e26ef9 into main Oct 19, 2026
45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant