首页 > 解决方案 > 使用 NextJS 的自托管字体

问题描述

我正在尝试使用我的 NextJS 应用程序自托管 webfonts,但遇到了麻烦。这是 URL 浏览器尝试访问这些字体:

localhost:3000/_next/static/css/fonts/Avenir.woff2

实际路径是:

_project_dir/static/fonts/Avenir.woff2

我尝试在 _app.js 中包含链接,它确实下载了字体,但文本仍然没有样式。

<link rel="preload" as="font" href="/static/fonts/Avenir.woff2" type="font/woff2" crossorigin />

这是我的_app.js


  render() {
    const { Component, pageProps } = this.props;
    return (
      <Container>
        <link href="https://fonts.googleapis.com/css?family=Poppins:500,500i,600&display=swap" rel="stylesheet" />
        <link rel="preload" as="font" href="/static/fonts/Avenir.woff2" type="font/woff2" crossorigin />
        <link rel="preload" as="font" href="/static/fonts/AvenirHeavy.woff2" type="font/woff2" crossorigin />
        <Head>
          <title>Project</title>
        </Head>
        <Provider store={store}>
          <PersistGate loading={null} persistor={persistor}>
            <Component pageContext={this.pageContext} {...pageProps} />
          </PersistGate>
        </Provider>
      </Container>
    );
  }
}

我的main.css

@font-face {
  font-family: 'Avenir';
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url('fonts/Avenir.eot');
  src: url('fonts/Avenir.eot?#iefix') format('embedded-opentype'), url('fonts/Avenir.woff2') format('woff2'),
    url('fonts/Avenir.woff') format('woff'), url('fonts/Avenir.ttf') format('truetype');
}

@font-face {
  font-family: 'Avenir';
  font-weight: 500;
  src: url('fonts/Avenir.eot');
  src: url('fonts/Avenir.eot?#iefix') format('embedded-opentype'), url('fonts/Avenir.woff2') format('woff2'),
    url('fonts/Avenir.woff') format('woff'), url('fonts/Avenir.ttf') format('truetype');
}

@font-face {
  font-family: 'Avenir';
  font-weight: 900;
  src: url('fonts/AvenirHeavy.eot');
  src: url('fonts/AvenirHeavy.eot?#iefix') format('embedded-opentype'), url('fonts/AvenirHeavy.woff2') format('woff2'),
    url('fonts/AvenirHeavy.woff') format('woff'), url('fonts/AvenirHeavy.ttf') format('truetype');
}

我的next.config.js

  webpack(config, options) {
    config.module.rules.push({
      test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
      use: {
        loader: 'url-loader',
        options: {
          limit: 100000,
        },
      },
    });
    return config;
  },

标签: javascriptreactjsnext.jswebfontsweb-performance

解决方案


你不需要任何额外的依赖来使用字体。只需将您的字体移动到public/fonts而不是static/fonts.

然后预加载:

<link rel="preload" href="/fonts/Avenir.woff2" as="font" type="font/woff2" crossOrigin="anonymous" />

记得保留开头的斜线,否则将不起作用。根据官方文档

public然后,您的代码可以从基本 URL ( ) 开始引用其中的文件/

此外,在 JSX 中,它crossOrigin不是crossorigin,它需要 a string,而不是Boolean.

在 CSS/SCSS 中(在每个 src-url 中添加斜杠):

@font-face {
  /* ... */
  src: url('/fonts/Avenir.woff2') format('woff2');
  /* ... */
}

然后删除字体文件的自定义 webpack 配置。这种方法的缺点是字体不会像url-loader. 但是我相信无论如何内联所有字体都是非常低效的。(您设置了 . 的限制100000。几乎每个 woff/woff2 字体都将被内联。)


推荐阅读