Skip to content

Commit f0efee0

Browse files
committed
feat(v3-uplift): build /dev/components on previews, not production
The showcase was gated only by client-side NODE_ENV checks. Since next build sets NODE_ENV=production, the route existed and was fetchable on every deployed build — including Vercel previews, where it rendered blank — while all ~29 showcase modules still shipped in the production bundle. Unusable where it was wanted, shipped where it wasn't. Gates it via pageExtensions instead, the same build-time mechanism already used for the *.governance.tsx pages (PR #379, 'feat: conditional build'). Renaming the pages to *.dev.tsx means Next never sees them unless that extension is registered: no route, no chunk, a real 404 rather than a blank page. The now-redundant NODE_ENV guards are removed — they would have kept the page blank on preview. VERCEL_ENV is Vercel's documented system variable for per-environment behaviour, so previews work with no dashboard setup. The VERCEL_ENV !== 'production' veto is deliberate: without it the gate is purely additive, and NEXT_PUBLIC_ENABLE_DEV_PAGES=true left scoped to all environments would leak the showcase into production.
1 parent 3e52e6a commit f0efee0

5 files changed

Lines changed: 19 additions & 9 deletions

File tree

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ NEXT_PUBLIC_GOVERNANCE_CACHE_URL=https://governance-cache-api.aave.com/graphql
88
# Client on/off gate for gasless voting. The relay only works if GELATO_SPONSOR_KEY is also set server-side.
99
NEXT_PUBLIC_ENABLE_GASLESS_VOTING=false
1010
NEXT_PUBLIC_ENABLE_STAKING=true
11+
# Force-build the /dev/components showcase. Automatic on `next dev` and Vercel previews.
12+
NEXT_PUBLIC_ENABLE_DEV_PAGES=false
1113
NEXT_PUBLIC_API_BASEURL=https://aave-api-v2.aave.com
1214
NEXT_PUBLIC_TRANSAK_APP_URL=https://global.transak.com
1315
NEXT_PUBLIC_TRANSAK_API_URL=https://api.transak.com

custom.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace NodeJS {
66
interface ProcessEnv {
77
NEXT_PUBLIC_ENABLE_GOVERNANCE: string;
88
NEXT_PUBLIC_ENABLE_STAKING: string;
9+
NEXT_PUBLIC_ENABLE_DEV_PAGES?: string;
910
NEXT_PUBLIC_ENV: string;
1011
NEXT_PUBLIC_API_BASEURL: string;
1112
NEXT_PUBLIC_FORK_BASE_CHAIN_ID?: string;

next.config.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
88
const pageExtensions = ['page.tsx', 'ts'];
99
if (process.env.NEXT_PUBLIC_ENABLE_GOVERNANCE === 'true') pageExtensions.push('governance.tsx');
1010
if (process.env.NEXT_PUBLIC_ENABLE_STAKING === 'true') pageExtensions.push('staking.tsx');
11+
// Component showcase at `/dev/components`. Its pages are named `*.dev.tsx`, so unless that
12+
// extension is registered here Next never sees them: no route, no bundle, a real 404 rather than a
13+
// blank page. On for `next dev` and Vercel preview builds; off for the production IPFS build, which
14+
// sets neither. A `VERCEL_ENV` of `production` vetoes it outright, so a dashboard variable left
15+
// scoped to every environment by mistake still can't leak the showcase into production.
16+
const enableDevPages =
17+
process.env.VERCEL_ENV !== 'production' &&
18+
(process.env.NEXT_PUBLIC_ENABLE_DEV_PAGES === 'true' ||
19+
process.env.VERCEL_ENV === 'preview' ||
20+
process.env.NODE_ENV === 'development');
21+
if (enableDevPages) pageExtensions.push('dev.tsx');
1122

1223
/** @type {import('next').NextConfig} */
1324
module.exports = withSentryConfig(
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@ import { SHOWCASE_SECTIONS } from 'src/modules/dev/ComponentShowcase/utils/regis
55

66
/**
77
* One route per showcase section: `/dev/components/<slug>`. Renders only the active
8-
* section (lazily loaded via the registry) inside the shared sidebar layout. Dev-only.
8+
* section (lazily loaded via the registry) inside the shared sidebar layout. Only built when
9+
* dev pages are enabled (see `pageExtensions` in next.config.js).
910
*/
1011
export default function ComponentShowcaseSectionPage() {
1112
const router = useRouter();
1213

13-
if (process.env.NODE_ENV !== 'development') {
14-
return null;
15-
}
16-
1714
const slug = typeof router.query.section === 'string' ? router.query.section : '';
1815
const section = SHOWCASE_SECTIONS.find((s) => s.slug === slug);
1916
const ActiveSection = section?.Component;
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ import { useRouter } from 'next/router';
22
import { useEffect } from 'react';
33
import { SHOWCASE_SECTIONS } from 'src/modules/dev/ComponentShowcase/utils/registry';
44

5-
// `/dev/components` → redirect to the first section. Dev-only.
5+
// `/dev/components` → redirect to the first section. Only built when dev pages are enabled
6+
// (see `pageExtensions` in next.config.js).
67
export default function ComponentShowcaseIndexPage() {
78
const router = useRouter();
89

910
useEffect(() => {
10-
if (process.env.NODE_ENV === 'development') {
11-
router.replace(`/dev/components/${SHOWCASE_SECTIONS[0].slug}`);
12-
}
11+
router.replace(`/dev/components/${SHOWCASE_SECTIONS[0].slug}`);
1312
}, [router]);
1413

1514
return null;

0 commit comments

Comments
 (0)