使用 NextJS 的自托管字体
Posted
技术标签:
【中文标题】使用 NextJS 的自托管字体【英文标题】:Self-hosted fonts using NextJS 【发布时间】:2019-12-26 15:33:22 【问题描述】:我正在尝试使用我的 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;
,
【问题讨论】:
【参考方案1】:你不需要任何额外的依赖来使用字体。只需将您的字体移动到public/fonts
而不是static/fonts
。
然后预加载:
<link rel="preload" href="/fonts/Avenir.woff2" as="font" type="font/woff2" crossOrigin="anonymous" />
记得保留开头的斜线,否则将不起作用。根据official docs:
然后,您的代码可以从基本 URL (
/
) 开始引用public
中的文件。
另外,在 JSX 中,它是 crossOrigin
而不是 crossorigin
,它需要 string
,而不是 Boolean
。
在 CSS/SCSS 中(在每个 src-url 中添加斜杠):
@font-face
/* ... */
src: url('/fonts/Avenir.woff2') format('woff2');
/* ... */
然后删除字体文件的自定义 webpack 配置。这种方法的缺点是不会像url-loader
那样内联字体。但我相信无论如何内联所有字体是非常低效的。 (您设置了 100000
的限制。几乎所有 woff/woff2 字体都会被内联。)
【讨论】:
【参考方案2】:在较新版本的 next 中,我相信您可以 import
WOFF2 文件并在您的 CSS similar to this example 中为 Gatsby 使用它。但是,如果您没有导入字体文件,而是按照您的说明将它们放在/static/fonts
目录中,您可以通过硬编码静态目录@987654323 中的字体路径来避免使用WebPack 加载程序或next-fonts 之类的插件@:
import React, Fragment from "react";
const WebFonts = () => (
<Fragment>
<style global jsx>`
@font-face
font-family: "Source Sans Pro";
font-style: normal;
font-stretch: normal;
font-weight: 400;
font-display: fallback;
src: local("SourceSansPro Regular"), local("SourceSansPro-Regular"),
url(/static/fonts/SourceSansPro-Regular.woff2) format("woff2");
unicode-range: U+0100-024f, U+1-1eff, U+20a0-20ab, U+20ad-20cf, U+2c60-2c7f,
U+A720-A7FF;
@font-face
font-family: "Source Sans Pro";
font-style: normal;
font-weight: 600;
font-display: fallback;
src: local("SourceSansPro SemiBold"), local("SourceSansPro-SemiBold"),
url(/static/fonts/SourceSansPro-SemiBold.woff2) format("woff2");
unicode-range: U+0100-024f, U+1-1eff, U+20a0-20ab, U+20ad-20cf, U+2c60-2c7f,
U+A720-A7FF;
@font-face
font-family: "Source Sans Pro";
font-style: normal;
font-weight: 700;
font-display: fallback;
src: local("SourceSansPro SemiBold"), local("SourceSansPro-SemiBold"),
url(/static/fonts/SourceSansPro-Bold.woff2) format("woff2");
unicode-range: U+0100-024f, U+1-1eff, U+20a0-20ab, U+20ad-20cf, U+2c60-2c7f,
U+A720-A7FF;
`</style>
</Fragment>
);
export default WebFonts;
然后将该组件导入 NextJS 中的 _document
覆盖。这将使用添加到 NextJS 静态目录的字体。确保使用woff2 提供的woff2_compress
方法从Google Fonts 压缩任何TTF 字体下载,然后再为它们提供更好的页面速度。如果您没有在 DevTools 的网络瀑布中看到您的本地字体下载,请确保您通过删除这些字体的任何本地版本或 local
字体声明来进行测试。
【讨论】:
不,不能导入WOFF
/WOFF2
文件(在v10.2.3
中),除非他们有manually configured webpack
使用文件加载器/资产模块来处理字体文件。
@brc-dd 如果您想回答提出的问题,请回答提出的问题。这将允许其他人品尝您的反应。【参考方案3】:
url('/static/fonts/Avenir.eot')
必须包含这样的路径。
【讨论】:
以上是关于使用 NextJS 的自托管字体的主要内容,如果未能解决你的问题,请参考以下文章
为啥我从托管在 Firebase 上的 NextJs 应用程序仅针对 POST 请求收到“502 网关”错误?