我正在使用创建-反应-应用程序,不喜欢弹出。

不清楚通过@font-face导入并在本地加载的字体应该放在哪里。

也就是说,我在装载

@font-face {
  font-family: 'Myriad Pro Regular';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Regular'), url('MYRIADPRO-REGULAR.woff') format('woff');
}

有什么建议吗?

——编辑

包括丹在回答中提到的要点

➜  Client git:(feature/trivia-game-ui-2) ✗ ls -l public/static/fonts
total 1168
-rwxr-xr-x@ 1 maximveksler  staff  62676 Mar 17  2014 MYRIADPRO-BOLD.woff
-rwxr-xr-x@ 1 maximveksler  staff  61500 Mar 17  2014 MYRIADPRO-BOLDCOND.woff
-rwxr-xr-x@ 1 maximveksler  staff  66024 Mar 17  2014 MYRIADPRO-BOLDCONDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  66108 Mar 17  2014 MYRIADPRO-BOLDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  60044 Mar 17  2014 MYRIADPRO-COND.woff
-rwxr-xr-x@ 1 maximveksler  staff  64656 Mar 17  2014 MYRIADPRO-CONDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  61848 Mar 17  2014 MYRIADPRO-REGULAR.woff
-rwxr-xr-x@ 1 maximveksler  staff  62448 Mar 17  2014 MYRIADPRO-SEMIBOLD.woff
-rwxr-xr-x@ 1 maximveksler  staff  66232 Mar 17  2014 MYRIADPRO-SEMIBOLDIT.woff
➜  Client git:(feature/trivia-game-ui-2) ✗ cat src/containers/GameModule.css
.GameModule {
  padding: 15px;
}

@font-face {
  font-family: 'Myriad Pro Regular';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Regular'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-REGULAR.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Condensed';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Condensed'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-COND.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Semibold Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Semibold Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-SEMIBOLDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Semibold';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Semibold'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-SEMIBOLD.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Condensed Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Condensed Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-CONDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Condensed Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Condensed Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDCONDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Condensed';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Condensed'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDCOND.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLD.woff') format('woff');
}

当前回答

我的感觉是,如果你在你的网站上有本地的字体,你应该能够使用CSS字体加载API在运行时为你做字体加载,而不使用CSS文件。这是我写的一个React组件。它是基于上面user-rebo的答案,但尝试在使用后卸载字体。它似乎可以在火狐和Chrome浏览器中运行。代码是:

import React, { useEffect, PropsWithChildren, useRef } from "react";

type FontFaceFormat =
  | "woff"
  | "woff2"
  | "truetype"
  | "opentype"
  | "embedded-opentype"
  | "svg";

type FontWrapperProps = {
  fontName: string;
  fontURL: string;
  fontFormat?: FontFaceFormat;
};

/*
 * The FontWrapper class. Takes a fontName (like "Andika"), a fontURL (which
 * should go to the website's public folder), and an optional font type. Usage
 * should be as simple as:
 *
 * <FontWrapper fontName="Andika" fontURL="/fonts/Andika-Regular.ttf.woff2">
 *   <p>This is some text</p>
 * </FontWrapper>
 *
 * Note: document.fonts is of type FontFaceSet, which should include the add() and
 * delete() methods. However, the TypeScript libraries for Visual Studio Code
 * miss these. That's why I have two instances of "document.fonts as any" -
 * to make those red lines go away.
 */

export default function FontWrapper({
  fontName,
  fontURL,
  fontFormat = "woff2",
  children,
}: PropsWithChildren<FontWrapperProps>) {
  const fontRef = useRef(null);

  useEffect(() => {
    const loadFont = async () => {
      const font = new FontFace(
        fontName,
        `url(${fontURL}) format("${fontFormat}")`,
        {}
      );
      const fontResult = await font.load();
      fontRef.current = fontResult;
      await (document.fonts as any).add(font);
    };

    const unloadFont = async () => {
      await (document.fonts as any).delete(fontRef.current);
    };

    loadFont();

    return () => {
      unloadFont();
    };
  }, []);

  return <div style={{ fontFamily: fontName }}>{children}</div>;
}


用法是:

<FontWrapper fontName="Andika" fontURL="/fonts/Andika-Regular.ttf.woff2">
  <p>This is some text</p>
</FontWrapper>

其他回答

链接到react js的本地字体可能会失败。所以,我更喜欢使用在线css文件从谷歌链接字体。参考以下代码,

<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">

or

<style>
    @import url('https://fonts.googleapis.com/css?family=Roboto');
</style>

去谷歌字体https://fonts.google.com/ 选择如下图所示的字体:

复制并粘贴该url在新选项卡,你会得到css代码添加该字体。在这种情况下,如果你去

https://fonts.googleapis.com/css?family=Spicy+Rice

它会像这样打开:

4、复制并粘贴到你的style.css中,然后像这样简单地开始使用那种字体:

      <Typography
          variant="h1"
          gutterBottom
          style={{ fontFamily: "Spicy Rice", color: "pink" }}
        >
          React Rock
        </Typography>

结果:

我的感觉是,如果你在你的网站上有本地的字体,你应该能够使用CSS字体加载API在运行时为你做字体加载,而不使用CSS文件。这是我写的一个React组件。它是基于上面user-rebo的答案,但尝试在使用后卸载字体。它似乎可以在火狐和Chrome浏览器中运行。代码是:

import React, { useEffect, PropsWithChildren, useRef } from "react";

type FontFaceFormat =
  | "woff"
  | "woff2"
  | "truetype"
  | "opentype"
  | "embedded-opentype"
  | "svg";

type FontWrapperProps = {
  fontName: string;
  fontURL: string;
  fontFormat?: FontFaceFormat;
};

/*
 * The FontWrapper class. Takes a fontName (like "Andika"), a fontURL (which
 * should go to the website's public folder), and an optional font type. Usage
 * should be as simple as:
 *
 * <FontWrapper fontName="Andika" fontURL="/fonts/Andika-Regular.ttf.woff2">
 *   <p>This is some text</p>
 * </FontWrapper>
 *
 * Note: document.fonts is of type FontFaceSet, which should include the add() and
 * delete() methods. However, the TypeScript libraries for Visual Studio Code
 * miss these. That's why I have two instances of "document.fonts as any" -
 * to make those red lines go away.
 */

export default function FontWrapper({
  fontName,
  fontURL,
  fontFormat = "woff2",
  children,
}: PropsWithChildren<FontWrapperProps>) {
  const fontRef = useRef(null);

  useEffect(() => {
    const loadFont = async () => {
      const font = new FontFace(
        fontName,
        `url(${fontURL}) format("${fontFormat}")`,
        {}
      );
      const fontResult = await font.load();
      fontRef.current = fontResult;
      await (document.fonts as any).add(font);
    };

    const unloadFont = async () => {
      await (document.fonts as any).delete(fontRef.current);
    };

    loadFont();

    return () => {
      unloadFont();
    };
  }, []);

  return <div style={{ fontFamily: fontName }}>{children}</div>;
}


用法是:

<FontWrapper fontName="Andika" fontURL="/fonts/Andika-Regular.ttf.woff2">
  <p>This is some text</p>
</FontWrapper>

我添加了

@font-face {
    font-family: 'Sanchez-Regular';
    src: local('Sanchez-Regular'),url(../assets/fonts/Sanchez/Sanchez-Regular.ttf) format('truetype');
}

而且效果非常好 就像我们在index.css中使用其他字体一样

我花了整个上午的时间来解决这个堆栈问题。我在上面的答案中使用了Dan的第一个解决方案作为出发点。

问题

我有一个开发(在我的本地机器上)、登台和生产环境。我的登台和生产环境位于同一台服务器上。

应用程序通过acmeserver/~staging/note-taking-app部署到登台,生产版本位于acmeserver/note-taking-app(归咎于IT)。

所有媒体文件(如字体)在dev上加载都很好(即,react-scripts启动)。

然而,当我创建和上传登台和生产版本时,虽然.css和.js文件加载正常,但字体却不能。编译后的.css文件看起来有一个正确的路径,但是浏览器http请求得到了一些非常错误的路径(如下所示)。

编译后的main.fc70b10f.chunk.css文件:

@font-face {
  font-family: SairaStencilOne-Regular;
  src: url(note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf) ("truetype");
}

浏览器http请求如下所示。注意,当字体文件仅仅存在于/static/media/中时,它是如何添加到/static/css/中的,以及如何复制目标文件夹。我排除了服务器配置是罪魁祸首的可能性。

推荐人也有部分过错。

GET /~staging/note-taking-app/static/css/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf HTTP/1.1
Host: acmeserver
Origin: http://acmeserver
Referer: http://acmeserver/~staging/note-taking-app/static/css/main.fc70b10f.chunk.css

包。Json文件首页属性设置为。/ notes -taking-app。这就是问题的根源。

{
  "name": "note-taking-app",
  "version": "0.1.0",
  "private": true,
  "homepage": "./note-taking-app",
  "scripts": {
    "start": "env-cmd -e development react-scripts start",
    "build": "react-scripts build",
    "build:staging": "env-cmd -e staging npm run build",
    "build:production": "env-cmd -e production npm run build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
  //...
}

解决方案

这很冗长,但解决方案是:

根据环境改变PUBLIC_URL env变量 从包中删除主页属性。json文件

下面是我的.env-cmdrc文件。我使用.env-cmdrc而不是常规的.env,因为它将所有内容都放在一个文件中。

{
  "development": {
    "PUBLIC_URL": "",
    "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
  },
  "staging": {
    "PUBLIC_URL": "/~staging/note-taking-app",
    "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
  },
  "production": {
    "PUBLIC_URL": "/note-taking-app",
    "REACT_APP_API": "http://acmeserver/note-taking-app/api"
  }
}

通过react-router-dom进行路由也可以,只需使用PUBLIC_URL env变量作为basename属性即可。

import React from "react";
import { BrowserRouter } from "react-router-dom";

const createRouter = RootComponent => (
  <BrowserRouter basename={process.env.PUBLIC_URL}>
    <RootComponent />
  </BrowserRouter>
);

export { createRouter };

服务器配置被设置为将所有请求路由到。/index.html文件。

最后,下面是实现上述更改后编译的main.fc70b10f.chunk.css文件的样子。

@font-face {
  font-family: SairaStencilOne-Regular;
  src: url(/~staging/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf)
    format("truetype");
}

阅读材料

https://create-react-app.dev/docs/adding-custom-environment-variables#adding-development-environment-variables-in-env https://create-react-app.dev/docs/deployment#serving-apps-with-client-side-routing https://create-react-app.dev/docs/advanced-configuration this explains the PUBLIC_URL environment variable Create React App assumes your application is hosted at the serving web server's root or a subpath as specified in package.json (homepage). Normally, Create React App ignores the hostname. You may use this variable to force assets to be referenced verbatim to the url you provide (hostname included). This may be particularly useful when using a CDN to host your application.