Skip to content

feat(build): support prerender vite config - #2415

Merged
james-elicx merged 6 commits into
mainfrom
codex/prerender-config
Jun 29, 2026
Merged

james-elicx merged 6 commits into
mainfrom
codex/prerender-config

Conversation

@james-elicx

Copy link
Copy Markdown
Member

Summary

  • add vinext({ prerender: true }) and vinext({ prerender: { routes: "*" } }) as build/deploy prerender triggers
  • keep --prerender-all supported and highest priority
  • add focused config and deploy wiring coverage for config-triggered prerender

Validation

  • vp check packages/vinext/src/config/prerender.ts packages/vinext/src/index.ts packages/vinext/src/cli.ts packages/vinext/src/deploy.ts tests/prerender-config.test.ts tests/deploy-prerender-config.test.ts
  • vp test run tests/prerender-config.test.ts tests/deploy-prerender-config.test.ts tests/cli-args.test.ts tests/deploy.test.ts

Review

  • Independent sub-agent review completed; initial test coverage finding was addressed, follow-up review returned NO FINDINGS.

@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

@ask-bonk ask-bonk 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.

Review: feat(build): support prerender vite config

Reviewed the full diff, ran the targeted test suites (prerender-config, deploy-prerender-config, cli-args, deploy — all green), and vp check on every changed file (clean). The implementation is solid and follows the repo's layering guidance well.

What's good

  • Clean extraction. Prerender decision logic lives in a typed config/prerender.ts module rather than inline in the generated/CLI code, consistent with AGENTS.md ("move real behavior into normal typed modules"). resolveVinextPrerenderDecision and formatVinextPrerenderLabel are pure and unit-tested.
  • Dev/deploy parity. Both cli.ts buildApp() and deploy.ts route through the same resolveVinextPrerenderDecision + formatVinextPrerenderLabel helpers, so the build and deploy paths can't drift. The enablePrerenderSourceMaps handling matches in both.
  • Priority is correct and explicit. --prerender-all > output: 'export' > vinext({ prerender }), matching the PR description and the prior || behavior, now with distinct labels per trigger.
  • Validation throws on bad input (false, non-"*" routes) with actionable messages, and undefined/null are treated as disabled with no false positives in findVinextPrerenderConfigInPlugins (the null property value is falsy and skipped).
  • flattenPluginOptions correctly handles vinext's PluginOption[] return and nested arrays.

Minor observations (non-blocking)

  1. CLI build wiring lacks an integration test. The deploy path gets tests/deploy-prerender-config.test.ts, but there's no equivalent end-to-end test exercising loadBuildViteConfigMetadata → resolveVinextPrerenderDecision inside cli.ts buildApp(). The unit pieces are covered, but the build-command wiring (the analog of what the deploy test verifies) is only covered transitively. Consider a focused test mirroring the deploy one for the vinext build path.

  2. Non-standard plugin property. Attaching __vinextPrerenderConfig to the vinext:config plugin object and reading it back via findVinextPrerenderConfigInPlugins relies on Vite preserving unknown plugin keys (it does today). This is a reasonable, low-cost channel, but it's an implicit contract worth a one-line comment near the property definition in index.ts so a future reader knows why a Vite plugin carries a custom field.

  3. Deploy loads the Vite config an extra time. When !skipBuild, runBuild instantiates the config and then the prerender step calls loadVinextPrerenderConfigFromViteConfig again (instantiating plugins a second time). Dynamic import() of Vite is cached so the cost is small, but instantiating the user's plugin array twice could surprise plugins with construction-time side effects. Not a regression introduced by correctness concerns — just noting it.

Overall: LGTM. No correctness or parity issues found; the items above are coverage/clarity nits.

@ask-bonk

ask-bonk Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review posted to PR #2415.

Summary

I reviewed PR #2415 (feat(build): support prerender vite config), ran the targeted test suites (all green), and ran vp check on every changed file (clean).

The implementation is solid. No correctness, parity, or security issues found. Highlights:

  • Logic is cleanly extracted into a typed config/prerender.ts module (per AGENTS.md guidance), with pure, unit-tested helpers.
  • The CLI build path and deploy path both route through the same resolveVinextPrerenderDecision / formatVinextPrerenderLabel helpers, so they can't drift — good dev/deploy parity, including enablePrerenderSourceMaps.
  • Priority ordering (--prerender-all > output: 'export' > vinext({ prerender })) is correct and matches the prior || behavior.
  • Input validation throws with actionable messages; undefined/null correctly treated as disabled with no false positives.

Minor, non-blocking observations I noted in the review:

  1. No integration test for the vinext build command wiring (deploy has one in tests/deploy-prerender-config.test.ts; build only has transitive unit coverage).
  2. The __vinextPrerenderConfig property on the Vite plugin object is an implicit contract — worth a one-line comment.
  3. Deploy instantiates the user's Vite plugin array a second time for the prerender config load (cheap, but could surprise plugins with construction-time side effects).

All three are coverage/clarity nits, not defects.

github run

@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

@ask-bonk ask-bonk 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.

Review: feat(build): support prerender vite config

Reviewed the full diff (16 files), ran the targeted suites (prerender-config, deploy-prerender-config, init-platform, init, init-cloudflare — 181 tests, all green), and ran vp check on all 7 changed source files (clean: format + lint + types). The implementation is solid and follows the repo's layering and parity guidance.

What's good

  • Clean extraction per AGENTS.md. Decision logic lives in a typed config/prerender.ts module with pure, unit-tested helpers (normalizeVinextPrerenderConfig, resolveVinextPrerenderDecision, formatVinextPrerenderLabel, findVinextPrerenderConfigInPlugins) rather than inline in the CLI/deploy code.
  • Build/deploy parity. Both cli.ts buildApp() and deploy.ts step 6a route through the same resolveVinextPrerenderDecision + formatVinextPrerenderLabel helpers, and both gate enablePrerenderSourceMaps identically, so the two prerender entry points can't drift.
  • Priority ordering is correct and explicit. --prerender-all > output: 'export' > vinext({ prerender }), matching the prior || behavior with distinct labels per trigger.
  • Validation surfaces early. normalizeVinextPrerenderConfig is called at the top of vinext(), so invalid config (false, non-"*" routes) throws at config-load time with actionable messages; undefined/null are correctly treated as disabled with no false positives.
  • End-to-end coverage exists for the build path. The ppr-impact-demo fixture and Playwright project were migrated from --prerender-all to vinext({ prerender: { routes: "*" } }) + plain vinext build, so the loadBuildViteConfigMetadata → resolveVinextPrerenderDecision wiring is exercised end-to-end by E2E, not just transitively. The deploy path additionally gets a focused integration test.
  • No arg collision. parsePrerenderArg uses exact match for --prerender and startsWith("--prerender="), so it won't accidentally match the build/deploy --prerender-all flag (which lives on a different command anyway).
  • AST init editing reuses the established pattern. hasVinextPrerender / ensureVinextPrerender mirror the existing cache/image-optimizer helpers (including the SpreadElement guard and the empty-args vs object-args branches), and throw a clear error when plugin options aren't a static object.

Minor observations (non-blocking)

  1. Deploy loads the user's Vite config an extra time. In deploy.ts step 6a, loadVinextPrerenderConfigFromViteConfig calls loadConfigFromFile unconditionally — even when --prerender-all is already set (where the result is discarded) and even when !skipBuild (where runBuild already instantiated the config). Dynamic import() of Vite is cached so the cost is small, but instantiating the user's plugin array a second time could surprise plugins with construction-time side effects. Cheap win: short-circuit the config load when options.prerenderAll is already true, since the flag wins regardless.

  2. __vinextPrerenderConfig is an implicit cross-process contract. The normalized config is smuggled from index.ts onto the vinext:config plugin object and read back via findVinextPrerenderConfigInPlugins after a fresh loadConfigFromFile. This relies on Vite preserving unknown plugin keys (true today) and is a reasonable low-cost channel — worth a one-line comment near the property definition in index.ts and VINEXT_PRERENDER_CONFIG_PLUGIN_PROPERTY so a future reader knows why a Vite plugin carries a custom field.

Both are clarity/efficiency nits, not defects.

Verdict: LGTM. No correctness, parity, or security issues found.

@ask-bonk

ask-bonk Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review posted to PR #2415.

Summary

I reviewed PR #2415 (feat(build): support prerender vite config) — full diff across all 16 files. I ran the targeted test suites (prerender-config, deploy-prerender-config, init-platform, init, init-cloudflare — 181 tests, all green) and vp check on all 7 changed source files (clean).

The implementation is solid — no correctness, parity, or security issues found. Key strengths:

  • Decision logic is cleanly extracted into a typed, unit-tested config/prerender.ts module per AGENTS.md guidance.
  • Build (cli.ts) and deploy (deploy.ts) paths both route through the same resolveVinextPrerenderDecision + formatVinextPrerenderLabel helpers, so they can't drift — good parity, including enablePrerenderSourceMaps.
  • Priority ordering (--prerender-all > output: 'export' > config) is correct.
  • Validation throws early at config-load with actionable messages.
  • The ppr-impact-demo fixture/Playwright project was migrated to config-based prerender, so the build path is covered E2E (addressing the reviewer's earlier "no build integration test" nit).
  • No arg-parsing collision between --prerender (init) and --prerender-all (build/deploy).

Two non-blocking observations I flagged:

  1. Deploy calls loadConfigFromFile unconditionally in step 6a — even when --prerender-all already wins and even after runBuild already instantiated the config — re-running the user's plugin array. Suggested a short-circuit when prerenderAll is set.
  2. __vinextPrerenderConfig is an implicit cross-load contract worth a one-line comment in index.ts.

Both are clarity/efficiency nits, not defects. Verdict: LGTM.

github run

@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

@pkg-pr-new

pkg-pr-new Bot commented Jun 29, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@vinext/cloudflare@2415
npm i https://pkg.pr.new/vinext@2415

commit: 3a81d0b

@github-actions

Copy link
Copy Markdown
Contributor
Example Preview Production Original
app-router-cloudflare preview production
pages-router-cloudflare preview production
app-router-playground preview production original
realworld-api-rest preview production
nextra-docs-template preview production
benchmarks preview production
hackernews preview production original
workers-cache preview production
web preview production

@ask-bonk ask-bonk 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.

Review: feat(build): support prerender vite config

Reviewed the full diff (16 files). Ran the targeted suites — prerender-config, deploy-prerender-config, init-platform, init, init-cloudflare (182 tests, all green) — and vp check on all 7 changed source files (clean: format + lint + types).

The implementation is solid: clean extraction into a typed, unit-tested config/prerender.ts; both build (cli.ts) and deploy (deploy.ts) route through the same resolveVinextPrerenderDecision + formatVinextPrerenderLabel helpers so they can't drift; priority ordering (--prerender-all > output: 'export' > vinext({ prerender })) is correct; validation throws early with actionable messages; null config is correctly skipped in findVinextPrerenderConfigInPlugins; the init AST helpers mirror the existing cache/image patterns; and no --prerender / --prerender-all arg collision (exact-match switch in cli-args.ts, exact + --prerender= match in parsePrerenderArg).

One finding worth addressing before merge

deploy.ts step 6a now loads the Vite config unconditionally, which is a behavioral change for the --prerender-all deploy path — not just an efficiency nit.

On main, step 6a only read next.config and never touched the Vite config:

if (options.prerenderAll || isStaticExport) { ... }

After this PR, the path always calls loadVinextPrerenderConfigFromViteConfig → loadConfigFromFile:

const vite = await loadProjectViteApi(info.root);
const vinextPrerenderConfig = await withCloudflareEnv(buildEnv, () =>
  loadVinextPrerenderConfigFromViteConfig(vite, info.root),
);
const prerenderDecision = resolveVinextPrerenderDecision({
  prerenderAllFlag: options.prerenderAll,
  vinextPrerenderConfig,
  nextOutput: nextConfig.output,
});

Because prerenderAllFlag wins inside resolveVinextPrerenderDecision regardless of vinextPrerenderConfig, the config load is pure overhead when --prerender-all is set — but it now also runs in cases where it never ran before:

  • vinext deploy --prerender-all --skip-build: previously no Vite config was loaded at any point in deploy; now it is. If loadConfigFromFile throws (malformed config, a plugin with a construction-time side effect that fails, etc.), a deploy that previously succeeded now fails. This is a new failure mode, not just extra work.
  • Even in the !skipBuild case, runBuild already instantiated the user's plugin array via createBuilder; step 6a now instantiates it a second time, which can surprise plugins with construction-time side effects.

The deploy tests added here only cover the config-triggered path (vinext({ prerender })), so the --prerender-all case where the new load is unnecessary isn't exercised.

Suggested fix: short-circuit the config load when the flag already wins, since it takes priority regardless:

const vinextPrerenderConfig = options.prerenderAll
  ? null
  : await withCloudflareEnv(buildEnv, () =>
      loadVinextPrerenderConfigFromViteConfig(vite, info.root),
    );

(Also lets you skip loadProjectViteApi entirely in the flag case.) This restores prior behavior for --prerender-all and removes the redundant instantiation, while keeping the config-triggered path intact.

Minor (non-blocking)

  • __vinextPrerenderConfig is an implicit cross-load contract — the normalized config is attached to the vinext:config plugin object in index.ts and read back via findVinextPrerenderConfigInPlugins after a fresh loadConfigFromFile. This relies on Vite preserving unknown plugin keys (true today). A one-line comment near the property definition in index.ts and VINEXT_PRERENDER_CONFIG_PLUGIN_PROPERTY would help a future reader.

Parity note (not a defect)

Both prerender entry points (cli.ts buildApp() and deploy.ts step 6a) are covered and share the same helpers, including enablePrerenderSourceMaps. The Node platform's init path intentionally only writes prerender into newly-generated configs (existing configs are skipped when !force), matching its prior behavior — no AST update path exists there, which is consistent, not a regression.

Verdict: LGTM once the --prerender-all config-load short-circuit is addressed (or explicitly accepted as intended).

@ask-bonk

ask-bonk Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review posted to PR #2415.

Summary

Reviewed the full diff (16 files), ran the targeted suites (prerender-config, deploy-prerender-config, init-platform, init, init-cloudflare — 182 tests, all green), and ran vp check on all 7 changed source files (clean). The implementation is solid: shared decision helpers across build/deploy, correct priority ordering, early validation, and init AST helpers matching established patterns.

One finding worth addressing before merge:

deploy.ts step 6a now calls loadVinextPrerenderConfigFromViteConfig (→ loadConfigFromFile) unconditionally. On main, the --prerender-all deploy path never loaded the Vite config in step 6a. This is a behavioral change, not just an efficiency nit:

  • vinext deploy --prerender-all --skip-build previously loaded no Vite config at all; now it does, adding a new failure mode if loadConfigFromFile throws (malformed config, plugin construction side-effects).
  • In the !skipBuild case, the user's plugin array is instantiated a second time.

Since prerenderAllFlag wins inside resolveVinextPrerenderDecision regardless of the config value, the load can be safely short-circuited when options.prerenderAll is set — restoring prior behavior and removing the redundant instantiation. The new deploy tests only cover the config-triggered path, so this case isn't exercised.

Minor: __vinextPrerenderConfig is an implicit cross-load contract worth a one-line comment.

Everything else (parity, validation, arg collisions, Node init behavior) checks out. Verdict: LGTM once the --prerender-all short-circuit is addressed or explicitly accepted.

github run

@github-actions

github-actions Bot commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

Performance benchmarks

Compared 3a81d0b against base a3910e7 using alternating same-runner rounds. Next.js was unchanged and skipped.

0 improved · 1 regressed · 5 within ±1.5%

Scenario Framework Baseline Current Change
Client bundle size (gzip) vinext 124.0 KB 124.0 KB ⚫ +0.0%
Client entry size (gzip) vinext 118.8 KB 118.8 KB ⚫ +0.0%
Dev server cold start vinext 2.54 s 2.53 s ⚫ -0.2%
Production build time vinext 3.04 s 3.10 s 🔴 +1.9%
RSC entry closure size (gzip) vinext 95.2 KB 95.2 KB ⚫ -0.0%
Server bundle size (gzip) vinext 161.5 KB 161.5 KB ⚫ -0.0%

View detailed results and traces

🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head

@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

@ask-bonk

ask-bonk Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review: feat(build): support prerender vite config

Re-reviewed the full diff at 3f7dc72. Ran the targeted suites — prerender-config, deploy-prerender-config, init-cloudflare, init-platform, init (184 tests, all green), plus deploy + cli-args (317 tests, green) — and vp check on all 7 changed source files (clean: format + lint + types).

The prior finding is fully addressed

My previous review flagged that deploy.ts step 6a loaded the Vite config unconditionally, adding a new failure mode for vinext deploy --prerender-all. Commit 3f7dc72 resolves this with an explicit short-circuit:

const shouldLoadVinextPrerenderConfig = !options.prerenderAll && nextConfig.output !== "export";
const vinextPrerenderConfig = shouldLoadVinextPrerenderConfig
  ? await withCloudflareEnv(buildEnv, async () => {
      const vite = await loadProjectViteApi(info.root);
      return loadVinextPrerenderConfigFromViteConfig(vite, info.root);
    })
  : null;

This restores prior behavior: when --prerender-all or output: 'export' already wins, no Vite config is loaded and loadProjectViteApi is skipped entirely. Two new tests (writeProjectWithThrowingViteConfig) prove the short-circuit by asserting a deliberately throwing vite.config.ts is never loaded in the flag and static-export cases. Confirmed loadNextConfig/resolveNextConfig already ran unconditionally in step 6a on main, so the PR introduces no other behavioral change there.

The __vinextPrerenderConfig implicit-contract nit was also addressed with an explanatory comment in index.ts (line 1363) and on the constant definition.

What's good

  • Clean extraction into a typed, unit-tested config/prerender.ts; build (cli.ts) and deploy (deploy.ts) route through the same resolveVinextPrerenderDecision + formatVinextPrerenderLabel helpers including enablePrerenderSourceMaps, so they can't drift.
  • Priority ordering (--prerender-all > output: 'export' > vinext({ prerender })) is correct and matches the prior || behavior.
  • normalizeVinextPrerenderConfig validates early at config-load with actionable messages; undefined/null are treated as disabled with no false positives in findVinextPrerenderConfigInPlugins.
  • No --prerender / --prerender-all arg collision: parsePrerenderArg matches --prerender/--no-prerender exactly and --prerender= as a prefix; --prerender-all matches none of these and is handled by cli-args.ts's exact-match switch.
  • Init AST helpers (hasVinextPrerender, ensureVinextPrerender) mirror the established cache/image-optimizer patterns, including the SpreadElement guard and the empty-args vs object-args branches, and throw a clear error when plugin options aren't a static object.
  • The ppr-impact-demo fixture/Playwright project migrated to config-based prerender, so the build path is exercised E2E.

Parity note (not a defect)

The Node init path only writes prerender into newly-generated configs (existing configs skipped when !force), which matches its prior behavior — no AST update path exists there for Node, consistent with the existing cache/image handling.

Verdict: LGTM. No correctness, parity, or security issues found. The one prior blocking finding is resolved and covered by tests.

@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

@ask-bonk

ask-bonk Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review posted to PR #2415.

Summary

I re-reviewed PR #2415 (feat(build): support prerender vite config) at the latest commit 3f7dc72. Ran the targeted suites (prerender-config, deploy-prerender-config, init-cloudflare, init-platform, init — 184 tests; plus deploy + cli-args — 317 tests; all green) and vp check on all 7 changed source files (clean).

Verdict: LGTM — no issues found. The one blocking finding from the prior review round is now resolved.

Key points:

  • Prior finding fixed. The earlier review flagged that deploy.ts step 6a loaded the Vite config unconditionally, adding a new failure mode for vinext deploy --prerender-all. Commit 3f7dc72 adds an explicit shouldLoadVinextPrerenderConfig = !options.prerenderAll && nextConfig.output !== "export" short-circuit, restoring prior behavior, and adds two tests using a deliberately-throwing vite.config.ts to prove the config is never loaded when the flag/static-export wins.
  • I verified loadNextConfig/resolveNextConfig already ran unconditionally in step 6a on main, so no other behavioral change was introduced.
  • The __vinextPrerenderConfig implicit-contract nit was also addressed with explanatory comments.
  • Checked for genuine defects: priority ordering, early validation, null skip in findVinextPrerenderConfigInPlugins, no --prerender/--prerender-all arg collision, hybrid-build plugin re-instantiation, and AST init helpers mirroring existing cache/image patterns — all correct.

github run

@james-elicx
james-elicx marked this pull request as ready for review June 29, 2026 18:06
@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

@ask-bonk

ask-bonk Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review: feat(build): support prerender vite config

Re-reviewed the full diff at 3a81d0b (the latest commit adds the adapter-warning change that earlier review rounds did not cover). Ran the targeted suites — prerender-config, deploy-prerender-config, cache-adapters-config, image-adapters-config (56 tests), plus init-platform and init (128 tests) — all green. vp check on all 9 changed source files is clean (format + lint + types).

Verdict: LGTM — no correctness, parity, or security issues found. The one prior blocking finding is fully resolved and tested, and the changes not covered by earlier rounds check out.

Prior blocking finding is resolved and covered

The earlier review flagged that deploy.ts step 6a loaded the Vite config unconditionally, adding a new failure mode for vinext deploy --prerender-all. Commit 3f7dc72 adds the explicit short-circuit shouldLoadVinextPrerenderConfig = !options.prerenderAll && nextConfig.output !== "export", so loadProjectViteApi is skipped entirely when the flag or static-export already wins. Both short-circuit paths are now exercised by deploy-prerender-config.test.ts using a deliberately-throwing vite.config.ts (lines 133–150), proving the config is never loaded.

New since the last review round: adapter warning changes (commit 3a81d0b)

cache-adapters-virtual.ts and image-adapters-virtual.ts now inject a __vinextFormatAdapterError helper and log message instead of the full error object. Verified:

  • Falls back to String(error) for non-Error throws, with a try/catch guarding a throwing toString/Symbol.toPrimitive — returns '<unknown error>' rather than crashing the registration path. Sound.
  • The generated string concatenation ("...\n" + __vinextFormatAdapterError(error)) is correctly escaped (\\n in the template). Covered by the updated cache-adapters-config / image-adapters-config tests.

Spot checks that passed

  • Decision parity. Both cli.ts buildApp() and deploy.ts route through the same resolveVinextPrerenderDecision + formatVinextPrerenderLabel, including enablePrerenderSourceMaps. The decision is identical even though cli.ts always loads the config (it also needs emptyOutDir) while deploy.ts short-circuits — nextOutput === "export" is checked before vinextPrerenderConfig in the resolver, so priority is stable across both paths.
  • Priority ordering (--prerender-all > output: 'export' > vinext({ prerender })) matches the prior || behavior.
  • Arg collision. parsePrerenderArg matches --prerender/--no-prerender exactly and --prerender= as a prefix; --prerender-all / --prerender-concurrency match none of these, so the init prompt logic ignores build/deploy flags.
  • findVinextPrerenderConfigInPlugins correctly skips the null property value (set when prerender is undefined) via the if (prerenderConfig) truthiness check, and flattenPluginOptions handles vinext's nested PluginOption[] return.
  • AST init helpers (hasVinextPrerender, ensureVinextPrerender) mirror the existing cache/image patterns, including the SpreadElement guard and the empty-args vs object-args branches, and throw a clear error when plugin options aren't a static object.
  • Package export wiring. ./internal/config/prerender → ./dist/config/prerender.js is picked up by the src/**/*.ts build entry; deploy.ts imports it as a bare specifier. Resolves cleanly.

Parity note (not a defect)

The Node init path writes prerender only into newly-generated configs (existing configs skipped when !force via setupNodePlatform), with no AST update path — consistent with its existing cache/image handling. Only the Cloudflare init path has the AST-merge path. This is the established, intentional asymmetry.

@ask-bonk

ask-bonk Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review posted to PR #2415.

Summary

I re-reviewed PR #2415 (feat(build): support prerender vite config) at the latest commit 3a81d0b. Ran the targeted suites (prerender-config, deploy-prerender-config, cache-adapters-config, image-adapters-config — 56 tests; plus init-platform, init — 128 tests; all green) and vp check on all 9 changed source files (clean).

Verdict: LGTM — no correctness, parity, or security issues found.

Key points:

  • Prior blocking finding resolved. The deploy --prerender-all unconditional-config-load issue is fixed by the shouldLoadVinextPrerenderConfig short-circuit (3f7dc72) and now covered by two tests using a deliberately-throwing vite.config.ts.
  • Covered the changes earlier review rounds missed — the 3a81d0b adapter-warning change. The new __vinextFormatAdapterError helper safely extracts error messages with a try/catch around String(error) and correctly escapes the generated \n. Sound.
  • Verified decision parity between cli.ts and deploy.ts (shared helpers, stable priority even though deploy short-circuits the load), arg-collision safety, null skip in findVinextPrerenderConfigInPlugins, AST init helpers matching existing cache/image patterns, and correct ./internal/config/prerender export wiring.
  • Node init parity note (not a defect): the Node path has no AST-merge path, only Cloudflare does — the established asymmetry.

No new issues introduced; everything checks out.

github run

@james-elicx
james-elicx merged commit bcd4e44 into main Jun 29, 2026
60 checks passed
@james-elicx
james-elicx deleted the codex/prerender-config branch June 29, 2026 18:16
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.

1 participant