Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Font subsets in function call #41694

Merged
merged 6 commits into from Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1,901 changes: 1,901 additions & 0 deletions packages/font/src/google/index.ts

Large diffs are not rendered by default.

25 changes: 15 additions & 10 deletions packages/font/src/google/loader.ts
Expand Up @@ -21,16 +21,8 @@ const downloadGoogleFonts: FontLoader = async ({
data,
config,
emitFontFile,
isServer,
}) => {
if (!config?.subsets) {
Log.warn(
`${chalk.bold('@next/font/google')} is missing ${chalk.bold(
'options.subsets'
)} in your ${chalk.bold(
'next.config.js'
)}. Please specify subsets, otherwise no fonts will be preloaded.`
)
}
const subsets = config?.subsets || []

const {
Expand All @@ -43,7 +35,19 @@ const downloadGoogleFonts: FontLoader = async ({
fallback,
adjustFontFallback,
variable,
subsets: callSubsets,
} = validateData(functionName, data)

if (isServer && preload && !callSubsets && !config?.subsets) {
Log.warn(
`The ${chalk.bold('@next/font/google')} font ${chalk.bold(
fontFamily
)} has no selected subsets. Please specify subsets in the function call or in your ${chalk.bold(
'next.config.js'
)}, otherwise no fonts will be preloaded. Read more: https://nextjs.org/docs/api-reference/components/font#nextfontgoogle`
)
}

const fontAxes = getFontAxes(fontFamily, weight, style, selectedVariableAxes)
const url = getUrl(fontFamily, fontAxes, display)

Expand Down Expand Up @@ -72,7 +76,8 @@ const downloadGoogleFonts: FontLoader = async ({
if (googleFontFileUrl) {
fontFiles.push({
googleFontFileUrl,
preloadFontFile: !!preload && subsets.includes(currentSubset),
preloadFontFile:
!!preload && (callSubsets ?? subsets).includes(currentSubset),
})
}
}
Expand Down
3 changes: 3 additions & 0 deletions packages/font/src/google/utils.ts
Expand Up @@ -16,6 +16,7 @@ type FontOptions = {
fallback?: string[]
adjustFontFallback: boolean
variable?: string
subsets?: string[]
}
export function validateData(functionName: string, data: any): FontOptions {
let {
Expand All @@ -27,6 +28,7 @@ export function validateData(functionName: string, data: any): FontOptions {
fallback,
adjustFontFallback = true,
variable,
subsets,
} = data[0] || ({} as any)
if (functionName === '') {
throw new Error(`@next/font/google has no default export`)
Expand Down Expand Up @@ -98,6 +100,7 @@ export function validateData(functionName: string, data: any): FontOptions {
fallback,
adjustFontFallback,
variable,
subsets,
}
}

Expand Down
Expand Up @@ -78,6 +78,7 @@ export default async function nextFontLoader(this: any) {
src.startsWith('.') ? src : `./${src}`
),
fs: this.fs,
isServer,
})

const { postcss } = await getPostcss()
Expand Down
1 change: 1 addition & 0 deletions packages/next/font/index.d.ts
Expand Up @@ -19,6 +19,7 @@ export type FontLoader = (options: {
emitFontFile: (content: Buffer, ext: string, preload: boolean) => string
resolve: (src: string) => string
fs: any
isServer: boolean
}) => Promise<{
css: string
fallbackFonts?: string[]
Expand Down
4 changes: 3 additions & 1 deletion scripts/update-google-fonts.js
Expand Up @@ -15,7 +15,8 @@ const fetch = require('node-fetch')
type CssVariable = \`--\${string}\`
`
const fontData = {}
for (let { family, fonts, axes } of familyMetadataList) {
for (let { family, fonts, axes, subsets } of familyMetadataList) {
subsets = subsets.filter((subset) => subset !== 'menu')
const weights = new Set()
const styles = new Set()

Expand Down Expand Up @@ -61,6 +62,7 @@ const fetch = require('node-fetch')
preload?:boolean
fallback?: string[]
adjustFontFallback?: boolean
subsets?: Array<${subsets.map((subset) => `"${subset}"`).join('|')}>
${
optionalAxes
? `axes?:(${optionalAxes.map(({ tag }) => `'${tag}'`).join('|')})[]`
Expand Down
1 change: 1 addition & 0 deletions test/e2e/next-font/app/components/CompWithFonts.js
Expand Up @@ -5,6 +5,7 @@ const roboto = Roboto({
style: 'italic',
display: 'swap',
preload: true,
subsets: ['vietnamese'],
})

export default function Component() {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/next-font/index.test.ts
Expand Up @@ -303,7 +303,7 @@ describe('@next/font/google', () => {
expect($('link[as="font"]').get(1).attribs).toEqual({
as: 'font',
crossorigin: 'anonymous',
href: '/_next/static/media/4f3dcdf40b3ca86d.p.woff2',
href: '/_next/static/media/675c25f648fd6a30.p.woff2',
rel: 'preload',
type: 'font/woff2',
})
Expand Down
16 changes: 16 additions & 0 deletions test/unit/google-font-loader.test.ts
Expand Up @@ -85,6 +85,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
expect(css).toBe('OK')
expect(fetch).toHaveBeenCalledTimes(1)
Expand All @@ -105,6 +106,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
expect(adjustFontFallback).toEqual({
ascentOverride: '88.84%',
Expand All @@ -128,6 +130,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
expect(adjustFontFallback).toEqual({
ascentOverride: '80.28%',
Expand All @@ -151,6 +154,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
expect(adjustFontFallback).toEqual({
ascentOverride: '83.79%',
Expand All @@ -174,6 +178,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
expect(css).toBe('')
expect(fallbackFonts).toEqual(['system-ui', 'Arial'])
Expand All @@ -194,6 +199,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Failed to fetch font \`Alkalami\`.
Expand All @@ -210,6 +216,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"@next/font/google has no default export"`
Expand All @@ -225,6 +232,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Unknown font \`Unknown Font\`"`
Expand All @@ -240,6 +248,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Unknown weight \`123\` for font \`Inter\`.
Expand All @@ -256,6 +265,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Missing weight for font \`Abel\`.
Expand All @@ -272,6 +282,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Unknown style \`normal\` for font \`Molle\`.
Expand All @@ -288,6 +299,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Invalid display value \`invalid\` for font \`Inter\`.
Expand All @@ -304,6 +316,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Axes can only be defined for variable fonts"`
Expand All @@ -319,6 +332,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Font \`Lora\` has no definable \`axes\`"`
Expand All @@ -334,6 +348,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Invalid axes value for font \`Inter\`, expected an array of axes.
Expand All @@ -350,6 +365,7 @@ describe('@next/font/google loader', () => {
emitFontFile: jest.fn(),
resolve: jest.fn(),
fs: {} as any,
isServer: true,
})
).rejects.toThrowErrorMatchingInlineSnapshot(`
"Invalid axes value \`INVALID\` for font \`Roboto Flex\`.
Expand Down
8 changes: 8 additions & 0 deletions test/unit/local-font-loader.test.ts
Expand Up @@ -3,6 +3,7 @@ import loader from '@next/font/local/loader'
describe('@next/font/local', () => {
describe('generated CSS', () => {
test('Default CSS', async () => {
// @ts-expect-error
const { css } = await loader({
functionName: '',
data: [{ src: './my-font.woff2' }],
Expand All @@ -24,6 +25,7 @@ describe('@next/font/local', () => {
})

test('Weight and style', async () => {
// @ts-expect-error
const { css } = await loader({
functionName: '',
data: [{ src: './my-font.woff2', weight: '100 900', style: 'italic' }],
Expand All @@ -47,6 +49,7 @@ describe('@next/font/local', () => {
})

test('Other properties', async () => {
// @ts-expect-error
const { css } = await loader({
functionName: '',
data: [
Expand Down Expand Up @@ -81,6 +84,7 @@ describe('@next/font/local', () => {
describe('Errors', () => {
test('Not using default export', async () => {
await expect(
// @ts-expect-error
loader({
functionName: 'Named',
data: [],
Expand All @@ -96,6 +100,7 @@ describe('@next/font/local', () => {

test('Missing src', async () => {
await expect(
// @ts-expect-error
loader({
functionName: '',
data: [],
Expand All @@ -111,6 +116,7 @@ describe('@next/font/local', () => {

test('Invalid file extension', async () => {
await expect(
// @ts-expect-error
loader({
functionName: '',
data: [{ src: './font/font-file.abc' }],
Expand All @@ -126,6 +132,7 @@ describe('@next/font/local', () => {

test('Invalid display value', async () => {
await expect(
// @ts-expect-error
loader({
functionName: '',
data: [{ src: './font-file.woff2', display: 'invalid' }],
Expand All @@ -142,6 +149,7 @@ describe('@next/font/local', () => {

test('Invalid declaration', async () => {
await expect(
// @ts-expect-error
loader({
functionName: '',
data: [
Expand Down