Skip to content

Commit dc2de37

Browse files
Font optimization - Pass nonce to inlined font definition (vercel#21346)
1 parent 004ad62 commit dc2de37

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

packages/next/next-server/lib/post-process.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ async function processHTML(
8989
}
9090

9191
class FontOptimizerMiddleware implements PostProcessMiddleware {
92-
fontDefinitions: Array<string> = []
92+
fontDefinitions: (string | undefined)[][] = []
9393
inspect(
9494
originalDom: HTMLElement,
9595
_data: postProcessData,
@@ -112,8 +112,10 @@ class FontOptimizerMiddleware implements PostProcessMiddleware {
112112
)
113113
.forEach((element: HTMLElement) => {
114114
const url = element.getAttribute('data-href')
115+
const nonce = element.getAttribute('nonce')
116+
115117
if (url) {
116-
this.fontDefinitions.push(url)
118+
this.fontDefinitions.push([url, nonce])
117119
}
118120
})
119121
}
@@ -127,7 +129,7 @@ class FontOptimizerMiddleware implements PostProcessMiddleware {
127129
return markup
128130
}
129131
for (const key in this.fontDefinitions) {
130-
const url = this.fontDefinitions[key]
132+
const [url, nonce] = this.fontDefinitions[key]
131133
const fallBackLinkTag = `<link rel="stylesheet" href="${url}"/>`
132134
if (
133135
result.indexOf(`<style data-href="${url}">`) > -1 ||
@@ -136,16 +138,17 @@ class FontOptimizerMiddleware implements PostProcessMiddleware {
136138
// The font is already optimized and probably the response is cached
137139
continue
138140
}
139-
const fontContent = options.getFontDefinition(url)
141+
const fontContent = options.getFontDefinition(url as string)
140142
if (!fontContent) {
141143
/**
142144
* In case of unreachable font definitions, fallback to default link tag.
143145
*/
144146
result = result.replace('</head>', `${fallBackLinkTag}</head>`)
145147
} else {
148+
const nonceStr = nonce ? ` nonce="${nonce}"` : ''
146149
result = result.replace(
147150
'</head>',
148-
`<style data-href="${url}">${fontContent}</style></head>`
151+
`<style data-href="${url}"${nonceStr}>${fontContent}</style></head>`
149152
)
150153
}
151154
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react'
2+
import Head from 'next/head'
3+
4+
const Page = () => {
5+
return (
6+
<>
7+
<Head>
8+
<link
9+
href="https://fonts.googleapis.com/css2?family=Modak"
10+
rel="stylesheet"
11+
nonce="VmVyY2Vs"
12+
/>
13+
</Head>
14+
<div>Hi!</div>
15+
</>
16+
)
17+
}
18+
19+
export default Page

test/integration/font-optimization/test/index.test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ function runTests() {
5252
)
5353
})
5454

55+
it('should pass nonce to the inlined font definition', async () => {
56+
const html = await renderViaHTTP(appPort, '/nonce')
57+
expect(await fsExists(builtPage('font-manifest.json'))).toBe(true)
58+
expect(html).toContain(
59+
'<link rel="stylesheet" nonce="VmVyY2Vs" data-href="https://fonts.googleapis.com/css2?family=Modak"/>'
60+
)
61+
expect(html).toMatch(
62+
/<style data-href="https:\/\/fonts\.googleapis\.com\/css2\?family=Modak" nonce="VmVyY2Vs">.*<\/style>/
63+
)
64+
})
65+
5566
it('should inline the google fonts for static pages with Next/Head', async () => {
5667
const html = await renderViaHTTP(appPort, '/static-head')
5768
expect(await fsExists(builtPage('font-manifest.json'))).toBe(true)

0 commit comments

Comments
 (0)