Conversation
Match Next.js's diagnostic that next.config i18n applies to Pages Router and is unsupported by App Router. Detect both app and src/app, use the actual config filename, and reuse the existing warning deduplication. Pages-only projects retain their supported i18n configuration without a warning. Validation: - Original v16.2.6 i18n-hybrid suite: 10/10 passed. Routing already passed; the previously missing warning assertion now passes as well. - New root/src-app warning regressions fail before the change, verify no warning without App Router, and verify repeated resolution warns once. - Complete next-config suite: 240 passed. - Targeted vp check and vinext package build pass.
@vinext/cloudflare
create-vinext-app
@vinext/types
vinext
@cloudflare/workers-response-store
commit: |
Performance benchmarksCompared 0 improved · 0 regressed · 6 within ±1.5%
View detailed results and traces 🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head |
|
/bigbonk review for issues Time limit: 8 minutes. Complete the review and post all findings within that limit. |
| ? await resolveNextConfigInput(buildConfigMetadata.nextConfig, PHASE_PRODUCTION_BUILD) | ||
| : await loadNextConfig(root, PHASE_PRODUCTION_BUILD); | ||
| const resolvedNextConfig = await resolveNextConfig(rawNextConfig, root); | ||
| const resolvedNextConfig = await resolveNextConfig(rawNextConfig, root, { hasAppDir: isApp }); |
There was a problem hiding this comment.
[P2] Honor the configured active router in the CLI preflight
isApp comes from hasAppDir(root) before buildConfigMetadata.routeRootConfig is considered. Consequently, vinext build for a hybrid tree configured with vinext({ disableAppRouter: true }) still emits this App Router warning during the CLI resolution; the later plugin resolution with hasAppDir: false cannot retract it. The new test uses createBuilder() directly, so it does not exercise this CLI path. Please derive the flag from the route-root metadata (including disableAppRouter and a custom appDir) before passing it here.
|
Posted 1 actionable inline finding. |
|
/bigbonk review for issues Time limit: 8 minutes. Complete the review and post all findings within that limit. |
| const isApp = | ||
| !routeRootConfig?.disableAppRouter && | ||
| (routeRootConfig?.appDir | ||
| ? fs.existsSync(path.join(path.resolve(root, routeRootConfig.appDir), "app")) |
There was a problem hiding this comment.
[P2] Resolve appDir from the effective Vite root
VinextOptions.appDir is documented as relative to the Vite root, and the plugin resolves it against config.root in index.ts. This preflight instead resolves it against the CLI cwd. For example, with root: "frontend", vinext({ appDir: "." }), and frontend/app, the plugin activates App Router but this computes isApp = false, suppressing the warning. The same flag also controls React upgrading and hybrid-build setup below, so the CLI can select the wrong build path. Please carry the loaded config's effective root into this detection (ideally sharing the plugin's route-root resolution); the new custom-directory test only covers the cwd-as-root case.
|
Posted 1 actionable inline finding. |
|
/bigbonk review for issues Time limit: 8 minutes. Complete the review and post all findings within that limit. |
| // in its config() hook for each case, so cloudflare() and the plain Node SSR | ||
| // build both work correctly. | ||
| const isHybrid = isApp && hasPagesDir(); | ||
| const isHybrid = isApp && hasPagesDir(buildConfigMetadata.effectiveRoot); |
There was a problem hiding this comment.
[P2] Detect Pages from the configured route base
When appDir is set, it is the base containing both app/ and pages/ (and the plugin derives both directories from it), but this check still looks under effectiveRoot. In the new custom fixture, custom/app makes isApp true while the untouched root pages/ makes isHybrid true, so the subsequent vinext({ disableAppRouter: true }) build includes root Pages routes that the configured plugin intentionally ignores. Resolve the Pages directory from the same routeRootConfig/base directory as the App directory, and carry that base into the secondary build.
|
Posted 1 actionable inline finding. |
|
/bigbonk review for issues Time limit: 8 minutes. Complete the review and post all findings within that limit. |
| mode: buildMode, | ||
| configFile: false, | ||
| plugins: [...userTransformPlugins, vinext({ disableAppRouter: true })], | ||
| plugins: [...userTransformPlugins, vinext({ appDir: routeBase, disableAppRouter: true })], |
There was a problem hiding this comment.
[P2] Run the hybrid Pages build from the effective Vite root
Passing the absolute routeBase fixes route discovery, but this vite.build still receives root = process.cwd() above. For the new root: "frontend" hybrid case, the primary build writes under frontend/dist and loads frontend/next.config.mjs, while this pass writes dist/server/entry.js at the CLI cwd and searches that cwd for next.config.*. The command therefore exits successfully with split artifacts and a Pages bundle missing the effective project's Next config. Use buildConfigMetadata.effectiveRoot as this build's root (and keep the post-build paths on that same root); the test should assert the resulting hybrid artifacts, not only the log line.
|
Posted 1 actionable inline finding. |
|
/bigbonk review for issues Time limit: 8 minutes. Complete the review and post all findings within that limit. |
| ? await resolveNextConfigInput(buildConfigMetadata.nextConfig, PHASE_PRODUCTION_BUILD) | ||
| : await loadNextConfig(root, PHASE_PRODUCTION_BUILD); | ||
| const resolvedNextConfig = await resolveNextConfig(rawNextConfig, root); | ||
| const resolvedNextConfig = await resolveNextConfig(rawNextConfig, root, { |
There was a problem hiding this comment.
[P2] Read the warning config from the effective Vite root
hasActiveAppRouter is now correctly derived from buildConfigMetadata.effectiveRoot, but rawNextConfig and this filename lookup still use the CLI cwd. With root: "frontend", a root-level next.config.mjs containing i18n and an i18n-free frontend/next.config.mjs, the preflight emits an unsupported-App-Router warning even though the active project's config does not configure i18n. The inverse relies on the later plugin pass instead of this preflight. Preserve the existing build config resolution if needed, but load/resolve the config used for this diagnostic from effectiveRoot; the new Vite-root test avoids the disk-config case by supplying inline nextConfig.
|
Posted 1 actionable inline finding. |
|
/bigbonk review for issues Time limit: 8 minutes. Complete the review and post all findings within that limit. |
| warnDeprecatedConfigOptions( | ||
| config, | ||
| root, | ||
| options.hasAppDir ?? ["app", "src/app"].some((dir) => fs.existsSync(path.join(root, dir))), |
There was a problem hiding this comment.
[P2] Propagate active router state to deploy config resolution
This fallback makes every caller that omits hasAppDir treat a conventional directory as active, but the Cloudflare deploy preflight at packages/cloudflare/src/deploy.ts:2048 calls resolveNextConfig(rawNextConfig, info.root) even though it has already loaded viteConfigMetadata.routeRootConfig. Consequently, vinext({ disableAppRouter: true }) with an app/ directory emits this unsupported-App-Router warning during vinext-cloudflare deploy, while a configured custom App Router can be missed (notably with --skip-build). Please derive the active App Router from the deploy metadata and pass it here, and audit the other non-plugin callers for the same distinction.
|
Posted 1 actionable inline finding. |
|
/bigbonk review for issues Time limit: 8 minutes. Complete the review and post all findings within that limit. |
| // The executed Vite config is authoritative. Source scans cannot see | ||
| // imported or composed cache objects and must not suppress valid metadata. | ||
| cacheConfig: await findVinextCacheConfigInPlugins(plugins), | ||
| effectiveRoot: path.resolve(root, loaded?.config.root ?? "."), |
There was a problem hiding this comment.
[P2] Resolve roots after Vite config hooks
loadConfigFromFile() only loads the raw exported config; it does not run plugin config hooks. If an earlier Vite plugin returns { root: "frontend" }, vinext itself receives frontend as its root, but this metadata pass keeps info.root, so hasActiveAppRouter checks the wrong tree and the i18n warning can be missed or emitted for an inactive app. The CLI metadata loader has the same pattern. Please obtain the resolved Vite root (after config hooks), or otherwise share the root that vinext actually receives, and add coverage for a plugin-supplied root.
|
Posted 1 actionable inline finding. |
Warn when a project with
apporsrc/appconfiguresi18nin its Next.js config, matching Next.js's diagnostic that this configuration is unsupported in App Router. The warning uses the actual config filename and existing deduplication; Pages-only projects receive no warning.Adds regressions for both App Router directory locations, config filenames, and repeated resolution, based on the Next.js i18n-hybrid suite.
The source commit records all 10 upstream i18n-hybrid tests and 240 next-config tests passing, along with targeted checks and package build. Tests were not rerun in this worktree because its local
vite-plusdependency is not installed.