Skip to content

Commit

Permalink
fix: handle network errors fetching font metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Feb 21, 2024
1 parent ca2ddb1 commit 7be6d40
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/assets.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fsp from 'node:fs/promises'
import { addDevServerHandler, useLogger, useNuxt } from '@nuxt/kit'
import { addDevServerHandler, useNuxt } from '@nuxt/kit'
import { eventHandler, createError } from 'h3'
import { fetch } from 'ofetch'
import { defu } from 'defu'
Expand All @@ -9,14 +9,14 @@ import { extname, join } from 'pathe'
import { filename } from 'pathe/utils'
import { hash } from 'ohash'

import { logger } from './logger'
import { formatToExtension, parseFont } from './css/render'
import type { FontFaceData, ModuleOptions, NormalizedFontFaceData } from './types'

// TODO: replace this with nuxt/assets when it is released
export function setupPublicAssetStrategy (options: ModuleOptions['assets'] = {}) {
const assetsBaseURL = options.prefix || '/_fonts'
const nuxt = useNuxt()
const logger = useLogger('@nuxt/fonts')
const renderedFontURLs = new Map<string, string>()

function normalizeFontData (faces: FontFaceData | FontFaceData[]): NormalizedFontFaceData[] {
Expand Down
16 changes: 12 additions & 4 deletions src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@ const storage = createStorage({
})
})

export async function cachedData<T = unknown> (key: string, fetcher: () => Awaitable<T>, ttl = 1000 * 60 * 60 * 24 * 7) {
export async function cachedData<T = unknown> (key: string, fetcher: () => Awaitable<T>, options?: {
onError?: (err: any) => Awaitable<T>
ttl?: number
}) {
const cached = await storage.getItem<null | { expires: number, data: T }>(key)
if (!cached || cached.expires < Date.now()) {
const data = await fetcher()
await storage.setItem(key, { expires: Date.now() + ttl, data })
return data
try {
const data = await fetcher()
await storage.setItem(key, { expires: Date.now() + (options?.ttl || 1000 * 60 * 60 * 24 * 7), data })
return data
} catch (err) {
if (options?.onError) { return options.onError(err) }
throw err
}
}
return cached.data
}
3 changes: 3 additions & 0 deletions src/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { useLogger } from '@nuxt/kit'

export const logger = useLogger('@nuxt/fonts')
5 changes: 2 additions & 3 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { addBuildPlugin, addTemplate, defineNuxtModule, resolveAlias, resolvePath, useLogger, useNuxt } from '@nuxt/kit'
import { addBuildPlugin, addTemplate, defineNuxtModule, resolveAlias, resolvePath, useNuxt } from '@nuxt/kit'
import jiti from 'jiti'

import local from './providers/local'
Expand All @@ -11,6 +11,7 @@ import { setupPublicAssetStrategy } from './assets'

import type { FontFaceData, FontFamilyManualOverride, FontFamilyProviderOverride, FontProvider, ModuleOptions, ResolveFontFacesOptions } from './types'
export type { ModuleOptions } from './types'
import { logger } from './logger'

const defaultValues = {
weights: [400],
Expand Down Expand Up @@ -48,8 +49,6 @@ export default defineNuxtModule<ModuleOptions>({
// Skip when preparing
if (nuxt.options._prepare) return

const logger = useLogger('@nuxt/fonts')

for (const key of ['weights', 'styles', 'subsets'] as const) {
options.defaults![key] ||= defaultValues[key] as any
}
Expand Down
15 changes: 13 additions & 2 deletions src/providers/bunny.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { hash } from 'ohash'
import type { FontProvider, ResolveFontFacesOptions } from '../types'
import { extractFontFaceData, addLocalFallbacks } from '../css/parse'
import { cachedData } from '../cache'
import { logger } from '../logger'

export default {
async setup () {
Expand All @@ -13,7 +14,12 @@ export default {
if (!isBunnyFont(fontFamily)) { return }

return {
fonts: await cachedData(`bunny:${fontFamily}-${hash(defaults)}-data.json`, () => getFontDetails(fontFamily, defaults))
fonts: await cachedData(`bunny:${fontFamily}-${hash(defaults)}-data.json`, () => getFontDetails(fontFamily, defaults), {
onError (err) {
logger.error(`Could not fetch metadata for \`${fontFamily}\` from \`bunny\`.`, err)
return []
}
})
}
},
} satisfies FontProvider
Expand All @@ -40,7 +46,12 @@ let fonts: BunnyFontMeta
const familyMap = new Map<string, string>()

async function initialiseFontMeta () {
fonts = await cachedData('bunny:meta.json', () => fontAPI<BunnyFontMeta>('/list', { responseType: 'json' }))
fonts = await cachedData('bunny:meta.json', () => fontAPI<BunnyFontMeta>('/list', { responseType: 'json' }), {
onError () {
logger.error('Could not download `bunny` font metadata. `@nuxt/fonts` will not be able to inject `@font-face` rules for bunny.')
return {}
}
})
for (const id in fonts) {
familyMap.set(fonts[id]!.familyName!, id)
}
Expand Down
15 changes: 13 additions & 2 deletions src/providers/google.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { hash } from 'ohash'
import type { FontProvider, ResolveFontFacesOptions } from '../types'
import { extractFontFaceData, addLocalFallbacks } from '../css/parse'
import { cachedData } from '../cache'
import { logger } from '../logger'

export default {
async setup () {
Expand All @@ -13,7 +14,12 @@ export default {
if (!isGoogleFont(fontFamily)) { return }

return {
fonts: await cachedData(`google:${fontFamily}-${hash(defaults)}-data.json`, () => getFontDetails(fontFamily, defaults))
fonts: await cachedData(`google:${fontFamily}-${hash(defaults)}-data.json`, () => getFontDetails(fontFamily, defaults), {
onError (err) {
logger.error(`Could not fetch metadata for \`${fontFamily}\` from \`google\`.`, err)
return []
}
})
}
},
} satisfies FontProvider
Expand All @@ -39,7 +45,12 @@ async function fetchFontMetadata () {
}

async function initialiseFontMeta () {
fonts = await cachedData('google:meta.json', fetchFontMetadata)
fonts = await cachedData('google:meta.json', fetchFontMetadata, {
onError () {
logger.error('Could not download `google` font metadata. `@nuxt/fonts` will not be able to inject `@font-face` rules for google.')
return []
}
})
}

function isGoogleFont (family: string) {
Expand Down

0 comments on commit 7be6d40

Please sign in to comment.