Skip to content

Explore Vite transform for next/font/google imports (eliminate generated font catalog) #200

@southpolesteve

Description

@southpolesteve

Context

PR #57 solved the immediate problem of missing named exports by code-generating all ~1,923 Google Font exports from the Google Fonts API. This works and tree-shakes correctly, but it requires maintaining a generated file that needs periodic re-runs as Google adds new fonts.

How Next.js Does It

Next.js handles next/font/google entirely at compile time via an SWC transform:

  1. SWC detects import { Inter } from 'next/font/google'
  2. Rewrites const inter = Inter({...}) into a CSS import with query params
  3. A webpack loader downloads fonts and generates @font-face CSS at build time

The next/font/google module in Next.js only contains declare function type stubs. There's zero runtime JavaScript. The font system is a compile-time illusion.

Proposed Approach

We could implement a similar pattern using a Vite transform hook:

  1. Detect import { X } from 'next/font/google' in the importing file
  2. Rewrite it to import { createFontLoader } from 'vinext/shims/font-google-base'; const X = createFontLoader("X Name");
  3. The transform derives the font family name from the export name (same logic the Proxy already uses)

Benefits

  • No generated file to maintain (no need to re-run a script when Google adds fonts)
  • Works for any font automatically, including ones Google hasn't added yet
  • Zero bundle overhead (only fonts actually used get createFontLoader calls)
  • Closer to how Next.js handles it architecturally

Considerations

  • Need to handle edge cases: re-exports, dynamic imports, barrel files
  • IDE autocomplete would still need the .d.ts declarations file (could keep generating that separately)
  • Must work correctly in all three Vite environments (RSC, SSR, client)

Current State

The generated catalog from PR #57 works well and is the right solution for now. This issue tracks exploring the transform approach as a future improvement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions