diff --git a/packages/font/src/google/loader.ts b/packages/font/src/google/loader.ts index 63c9359ad81a5..1a4d9da34f36e 100644 --- a/packages/font/src/google/loader.ts +++ b/packages/font/src/google/loader.ts @@ -1,15 +1,17 @@ import type { AdjustFontFallback, FontLoader } from 'next/font' // @ts-ignore -import fetch from 'next/dist/compiled/node-fetch' -// @ts-ignore import { calculateSizeAdjustValues } from 'next/dist/server/font-utils' import { fetchCSSFromGoogleFonts, + fetchFontFile, getFontAxes, getUrl, validateData, } from './utils' +const cssCache = new Map>() +const fontCache = new Map() + const downloadGoogleFonts: FontLoader = async ({ functionName, data, @@ -36,7 +38,14 @@ const downloadGoogleFonts: FontLoader = async ({ const fontAxes = getFontAxes(fontFamily, weight, style, selectedVariableAxes) const url = getUrl(fontFamily, fontAxes, display) - const fontFaceDeclarations = await fetchCSSFromGoogleFonts(url, fontFamily) + let cachedCssRequest = cssCache.get(url) + const fontFaceDeclarations = + cachedCssRequest ?? (await fetchCSSFromGoogleFonts(url, fontFamily)) + if (!cachedCssRequest) { + cssCache.set(url, fontFaceDeclarations) + } else { + cssCache.delete(url) + } // Find font files to download const fontFiles: Array<{ @@ -63,14 +72,13 @@ const downloadGoogleFonts: FontLoader = async ({ // Download font files const downloadedFiles = await Promise.all( fontFiles.map(async ({ googleFontFileUrl, preloadFontFile }) => { - let fontFileBuffer: Buffer - if (process.env.NEXT_FONT_GOOGLE_MOCKED_RESPONSES) { - fontFileBuffer = Buffer.from(googleFontFileUrl) + let cachedFontRequest = fontCache.get(googleFontFileUrl) + const fontFileBuffer = + cachedFontRequest ?? (await fetchFontFile(googleFontFileUrl)) + if (!cachedFontRequest) { + fontCache.set(googleFontFileUrl, fontFileBuffer) } else { - const arrayBuffer = await fetch(googleFontFileUrl).then((r: any) => - r.arrayBuffer() - ) - fontFileBuffer = Buffer.from(arrayBuffer) + fontCache.delete(googleFontFileUrl) } const ext = /\.(woff|woff2|eot|ttf|otf)$/.exec(googleFontFileUrl)![1] diff --git a/packages/font/src/google/utils.ts b/packages/font/src/google/utils.ts index 347cdcba1356b..a4b342ec922f5 100644 --- a/packages/font/src/google/utils.ts +++ b/packages/font/src/google/utils.ts @@ -141,6 +141,14 @@ export async function fetchCSSFromGoogleFonts(url: string, fontFamily: string) { return cssResponse } +export async function fetchFontFile(url: string) { + if (process.env.NEXT_FONT_GOOGLE_MOCKED_RESPONSES) { + return Buffer.from(url) + } + const arrayBuffer = await fetch(url).then((r: any) => r.arrayBuffer()) + return Buffer.from(arrayBuffer) +} + export function getFontAxes( fontFamily: string, weight: string, diff --git a/test/unit/google-font-loader.test.ts b/test/unit/google-font-loader.test.ts index 3bb967e7342ac..194b49c6297b8 100644 --- a/test/unit/google-font-loader.test.ts +++ b/test/unit/google-font-loader.test.ts @@ -183,17 +183,17 @@ describe('@next/font/google loader', () => { await expect( loader({ - functionName: 'Inter', - data: [], + functionName: 'Alkalami', + data: [{ variant: '400' }], config: { subsets: [] }, emitFontFile: jest.fn(), resolve: jest.fn(), fs: {} as any, }) ).rejects.toThrowErrorMatchingInlineSnapshot(` - "Failed to fetch font \`Inter\`. - URL: https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=optional" - `) + "Failed to fetch font \`Alkalami\`. + URL: https://fonts.googleapis.com/css2?family=Alkalami:wght@400&display=optional" + `) }) test('Missing config with subsets', async () => {