next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Fonts are loaded from `assetPrefix` client-side only

Open florian-milky opened this issue 3 years ago • 2 comments

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.

Screenshot 2022-08-18 at 10 07 38

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

florian-milky avatar Aug 18 '22 11:08 florian-milky

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?

florian-milky avatar Aug 18 '22 11:08 florian-milky

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"
/>

florian-milky avatar Oct 27 '22 13:10 florian-milky