next.js
next.js copied to clipboard
Fonts are loaded from `assetPrefix` client-side only
Verify canary release
- [X] I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: x64
Version: Darwin Kernel Version 19.6.0: Thu Jun 18 20:49:00 PDT 2020; root:xnu-6153.141.1~1/RELEASE_X86_64
Binaries:
Node: 14.17.5
npm: 6.14.14
Yarn: N/A
pnpm: N/A
Relevant packages:
next: 12.2.6-canary.1
eslint-config-next: N/A
react: 17.0.2
react-dom: 17.0.2
What browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
next start
Describe the Bug
Thanks to assetPrefix, it's easy to use a CDN for JS and CSS code.
However, it is interfering with fonts and is not working as expected.

It appears that the client code uses the assetPrefix for fonts, but the server-side generated code is not using it, creating mismatched requests.
Important note: our environment variables are used at runtime and not at build time, because we reuse the build for different environments.
Expected Behavior
Fonts to be handled consistently by assetPrefix. It should either work like JS and CSS file, or not be handled at all.
Link to reproduction
https://github.com/florian-milky/asset-font-bug
To Reproduce
1- npm run build
2- npm run copy
3- npx serve -C -p 3006 and in another tab: npm run start
4- open http://localhost:3000/
5- Debug network requests. Observe that font is preloaded from localhost:3000 and then loaded from localhost:3006
Related to that issue, I would like to understand how we could setup other types of assets (images) to use our CDN. We can't tweak webpack configuration because it is only called at build time. However I know that webpack has support for dynamic public path, and I would assume that assetPrefix is using that capability. Is it possible to plugin into that?
Workaround:
import getConfig from 'next/config';
const { publicRuntimeConfig } = getConfig();
/**
* Issue with nextjs not using assetPrefix server-side
* https://github.com/vercel/next.js/issues/39722
*/
export const getAssetUrlWithAssetPrefix = (assetUrl: string) =>
assetUrl.startsWith('/') ? `${publicRuntimeConfig.ASSET_PREFIX}${assetUrl}` : assetUrl;
In _app
import Font from '../assets/fonts/font.woff2';
...
<link
rel="preload"
href={getAssetUrlWithAssetPrefix(Font)}
as="font"
crossOrigin="anonymous"
/>