mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
696948aca4
* shim: rewrite buildGoogleFontsUrl on top of the new build-url helper
Replace the inline URL builder in shims/font-google-base.ts with a thin
wrapper around the pure buildGoogleFontsUrl helper from PR 1
(packages/vinext/src/build/google-fonts/build-url.ts). The shim still
takes a FontOptions object and still returns a CSS URL, so external
callers and the existing 84 unit tests are unaffected.
Two visible behaviour changes:
1. Empty options no longer emit `:wght@100..900`. They emit no axis
segment at all, which makes Google return the default static face
(HTTP 200) for every font, including narrow-axis families like Sen
that previously got HTTP 400. This is the dev fallback only; the
build plugin always pre-resolves the real axis range from metadata
in production.
2. Italic-only requests no longer drop the ital axis. Pre-fix the outer
guard `weights.length > 0 || styles.length > 0` entered the block
but the inner branch only handled the wght path, so a call like
`Inter({ style: ['italic'] })` produced `family=Inter&display=swap`
with no italic anywhere in the URL. The shim now derives an ital
array from style and falls back to weight '400' when ital is set
without an explicit weight, so Google has somewhere to attach the
ital axis in the URL.
The shim deliberately does not import font-data.json or validate.ts: a
388 KB metadata file in the Worker bundle would dwarf the rest of the
shim, and the production path already has the metadata-aware variant.
Refs #885.
* plugin: validate options against metadata, surface HTTP errors as build errors
Replace the inline URL builder in plugins/fonts.ts with the pipeline added
in PR 1: validateGoogleFontOptions parses the call's options against the
bundled font metadata, getFontAxes resolves the actual `wght` range for
variable fonts, and buildGoogleFontsUrl emits the URL.
Three behaviour changes:
1. Variable fonts called with no `weight` now request the font's real
axis range (Sen 400..800, Inter 100..900) instead of a hardcoded
100..900. This is the user-visible fix for issue #885: Sen returns
HTTP 200 with all five face files instead of HTTP 400.
2. Validation errors surface as build errors with the source file path
attached. Unknown family, missing weight on a static font (Anton,
Archivo Black, etc.), unknown weight, mixing 'variable' with explicit
weights, axes on non-variable fonts, invalid display values, and
missing/unknown subsets are now all caught at transform time. Pre-fix
these silently produced URLs that Google rejected at request time.
3. HTTP non-2xx responses from Google are now distinguished from network
errors. A 4xx/5xx is wrapped in GoogleFontsHttpError and surfaced
with the failing URL plus the response body, because pre-fix the
silent `catch { return; }` skipped self-hosting and let the runtime
CDN path retry the same broken URL in the browser. Network errors
(offline dev) still fall through silently to keep `vp dev` usable
without a connection.
The fontCache key is the URL, so existing on-disk caches under
`.vinext/fonts/<hash>/` will be stale for affected fonts after this
change. One refetch per font on the next build.
Refs #885.
* tests: regression coverage for the #885 narrow-axis bug and validator throws
Five new tests in tests/font-google.test.ts plus subset additions to
existing fixtures whose Inter() / Roboto() calls were missing them.
Shim regressions:
- buildGoogleFontsUrl with empty options must not emit `:wght@100..900`
- buildGoogleFontsUrl with style-only options must keep the ital axis
visible in the URL
Plugin regressions:
- Sen() with no weight must fetch `:wght@400..800`, not `:wght@100..900`
- unknown families throw a build error with the file path attached
- non-variable fonts called without an explicit weight throw at build
time instead of silently emitting a broken URL
- HTTP 4xx/5xx from Google surfaces as a build error containing the URL
and the response body
- network errors (DNS, ECONNREFUSED, AbortError) still fall through
silently so offline dev keeps working
The existing plugin transform tests passed `Inter({ weight: '400' })`
without subsets; the validator now treats that as a missing-subsets
error (matches Next.js behaviour), so those fixtures gain
`subsets: ['latin']`. The two nested-brace regression tests still
exercise the parser's balanced-brace logic but use a benign
`_placeholder` field instead of `axes: { wght: 400 }`, which is
semantically invalid for Inter under the new validator.
Refs #885.
* address google font review feedback
App Router
A minimal example of a Next.js App Router application.
Demonstrates server components, client components, dynamic routes, and API route handlers.
Running Locally
- Install dependencies:
pnpm install
- Start the dev server:
pnpm dev
- Build for production:
pnpm build
- Preview the production build:
pnpm preview