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

不清楚通过@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');
}

有两种选择:

使用进口

这是建议的选项。它确保您的字体通过构建管道,在编译期间获得哈希值,以便浏览器缓存正确工作,并且如果文件丢失,您将得到编译错误。

正如在“添加图像,字体和文件”中所描述的,你需要从JS中导入一个CSS文件。例如,src/index.js默认导入src/index.css:

import './index.css';

这样的CSS文件通过构建管道,可以引用字体和图像。例如,如果你把一个字体放在src/fonts/MyFont。Woff,你的index.css可能包括这个:

@font-face {
  font-family: 'MyFont';
  src: local('MyFont'), url(./fonts/MyFont.woff) format('woff');
  /* other formats include: 'woff2', 'truetype, 'opentype',
                            'embedded-opentype', and 'svg' */
}

注意我们是如何使用以./开头的相对路径的。这是一种特殊的符号,可以帮助构建管道(由Webpack提供支持)发现该文件。

通常这就足够了。

使用公用文件夹

如果出于某种原因,你不喜欢使用构建管道,而是使用“经典的方式”,你可以使用公共文件夹并将字体放在那里。

这种方法的缺点是,在编译用于生产时,文件不会得到哈希值,因此每次更改它们时都必须更新它们的名称,否则浏览器将缓存旧版本。

如果你想这样做,把字体放在公共文件夹的某个地方,例如,在public/fonts/MyFont.woff。如果你遵循这种方法,你也应该把CSS文件放到公共文件夹中,而不是从JS中导入它们,因为混合这些方法会非常混乱。如果你还想这样做,你会有public/index。css这样的文件。你必须手动添加<link>到这个样式表从public/index.html:

<link rel="stylesheet" href="%PUBLIC_URL%/index.css">

在里面,你会使用常规的CSS符号:

@font-face {
  font-family: 'MyFont';
  src: local('MyFont'), url(fonts/MyFont.woff) format('woff');
}

Notice how I’m using fonts/MyFont.woff as the path. This is because index.css is in the public folder so it will be served from the public path (usually it’s the server root, but if you deploy to GitHub Pages and set your homepage field to http://myuser.github.io/myproject, it will be served from /myproject). However fonts are also in the public folder, so they will be served from fonts relatively (either http://mywebsite.example/fonts or http://myuser.github.io/myproject/fonts). Therefore we use the relative path.

注意,由于我们在本例中避免了构建管道,因此它不会验证文件是否实际存在。这就是我不推荐这种方法的原因。另一个问题是index.css文件没有被缩小,也没有得到哈希值。因此,对于最终用户来说,速度会变慢,而且浏览器可能会缓存旧版本的文件。

使用哪种方式?

使用第一个方法(“使用导入”)。我只描述了第二个,因为这是你试图做的(从你的评论来看),但它有很多问题,应该是你在解决某些问题时的最后手段。


你可以使用WebFont模块,它极大地简化了这个过程。

render(){
  webfont.load({
     custom: {
       families: ['MyFont'],
       urls: ['/fonts/MyFont.woff']
     }
  });
  return (
    <div style={your style} >
      your text!
    </div>
  );
}

我犯了这样的错误。

@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i&amp;subset=cyrillic,cyrillic-ext,latin-ext";
@import "https://use.fontawesome.com/releases/v5.3.1/css/all.css";

它以这种方式正常工作

@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i&amp;subset=cyrillic,cyrillic-ext,latin-ext);
@import url(https://use.fontawesome.com/releases/v5.3.1/css/all.css);

以下是一些做到这一点的方法:

1. 导入字体

例如,要使用Roboto,请使用

yarn add typeface-roboto

or

npm install typeface-roboto --save

在index.js:

import "typeface-roboto";

有很多开源字体和大部分谷歌字体的npm包。你可以在这里看到所有的字体。所有的包都来自那个项目。

2. 对于由第三方托管的字体

比如谷歌字体,你可以去fonts. Google。com在那里你可以找到你可以放在public/index.html中的链接

就像这样

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

or

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

3.下载字体并将其添加到源代码中。

下载字体。例如,对于谷歌字体,您可以访问fonts.google.com。点击下载按钮下载字体。

移动字体到字体目录在你的src目录

src
|
`----fonts
|      |
|      `-Lato/Lato-Black.ttf
|       -Lato/Lato-BlackItalic.ttf
|       -Lato/Lato-Bold.ttf
|       -Lato/Lato-BoldItalic.ttf
|       -Lato/Lato-Italic.ttf
|       -Lato/Lato-Light.ttf
|       -Lato/Lato-LightItalic.ttf
|       -Lato/Lato-Regular.ttf
|       -Lato/Lato-Thin.ttf
|       -Lato/Lato-ThinItalic.ttf
|
`----App.css

现在,在app。css中添加这个

@font-face {
  font-family: 'Lato';
  src: local('Lato'), url(./fonts/Lato-Regular.otf) format('opentype');
}

@font-face {
    font-family: 'Lato';
    font-weight: 900;
    src: local('Lato'), url(./fonts/Lato-Bold.otf) format('opentype');
}

@font-face {
    font-family: 'Lato';
    font-weight: 900;
    src: local('Lato'), url(./fonts/Lato-Black.otf) format('opentype');
}

对于ttf格式,必须提到format('truetype')。对于woff, format('woff')

现在你可以在课堂上使用这种字体了。

.modal-title {
    font-family: Lato, Arial, serif;
    font-weight: black;
}

4. 使用web-font-loader包

使用

yarn add webfontloader

or

npm install webfontloader --save

在src/index.js中,你可以导入它并指定所需的字体

import WebFont from 'webfontloader';

WebFont.load({
   google: {
     families: ['Titillium Web:300,400,700', 'sans-serif']
   }
});

去谷歌字体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>

结果:


我花了整个上午的时间来解决这个堆栈问题。我在上面的答案中使用了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.


链接到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>

你可以在不需要CSS的情况下使用Web API FontFace构造函数(也可以是Typescript):

export async function loadFont(fontFamily: string, url: string): Promise<void> {
    const font = new FontFace(fontFamily, `local(${fontFamily}), url(${url})`);
    // wait for font to be loaded
    await font.load();
    // add font to document
    document.fonts.add(font);
    // enable font with CSS class
    document.body.classList.add("fonts-loaded");
}
import ComicSans from "./assets/fonts/ComicSans.ttf";

loadFont("Comic Sans ", ComicSans).catch((e) => {
    console.log(e);
});

声明一个文件字体。ts与你的模块(仅ts):

declare module "*.ttf";
declare module "*.woff";
declare module "*.woff2";

如果TS无法找到FontFace类型作为其正式在制品,则将此声明添加到项目中。它可以在你的浏览器中运行,除了IE。


当使用不同的字体文件为正常/斜体字体风格时,您指定@font-face的方式可能需要根据入口点而不同。请看我的回答:

如果你选择将css文件直接链接到public/index.html,那么你通常可以使用一个字体家族名称和不同的字体风格的font-face:

@font-face {
  font-family: "FontName"; <---
  font-style: normal; <---
  font-weight: normal;
  src: url("path-to-assets/fonts/FontName.ttf") format("truetype");
}
@font-face {
  font-family: "FontName"; <---
  font-style: italic; <---
  font-weight: normal;
  src: url("path-to-assets/fonts/FontName-Italic.ttf") format("truetype");
}

/* Usage */
.text {
  font-family: FontName;
  font-style: normal;
}
.text-italic {
  font-family: FontName;
  font-style: italic;
}

如果你选择通过Js链接css文件进行捆绑,那么你需要为所有斜体字体设置一个不同的字体族名称,并使用正常的字体样式。

@font-face {
  font-family: "FontName"; <---
  font-style: normal; <---
  font-weight: normal; /* normal | 300 | 400 | 600 | bold | etc */
  src: url("path-to-assets/fonts/FontName.ttf") format("truetype");
}
@font-face {
  font-family: "FontNameItalic";
  font-style: normal; <----
  font-weight: normal; /* normal | 300 | 400 | 600 | bold | etc */
  src: url("path-to-assets/fonts/FontName-Italic.ttf") format("truetype");
}

/* Usage */
.text {
  font-family: FontName;
}
.text-italic {
  font-family: FontNameItalic;
}

我添加了

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

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


这是为使用NX(nwrl) monorepo的人准备的,我在那里使用它时测试了这个,可能适用于其他CRA应用程序。 首先在assets/fonts文件夹中添加字体,如果没有,创建一个字体文件夹。

然后在你的主app.js/tsx 将此代码与现有的jsx代码一起添加

<style type="text/css">{`
    @font-face {
      font-family: 'MaterialIcons';
      src: url(${require('react-native-vector-icons/Fonts/MaterialIcons.ttf')}) format('truetype');
    }
    @font-face {
      font-family: 'MaterialCommunityIcons';
      src: url(${require('react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf')}) format('truetype');
    }
    @font-face {
      font-family: 'Mulish-Bold';
      src: url(${require('../assets/fonts/Mulish-Bold.ttf')}) format('truetype');
    }
    @font-face {
      font-family: 'Your Font Name';
      src: url(${require('../assets/fonts/font-file-name.otf')}) format('truetype');
    }
  `}</style>

它应该看起来像这样,用Fragment标签包装

 <>
<style type="text/css">{`
        @font-face {
          font-family: 'MaterialIcons';
          src: url(${require('react-native-vector-icons/Fonts/MaterialIcons.ttf')}) format('truetype');
        }
        @font-face {
          font-family: 'MaterialCommunityIcons';
          src: url(${require('react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf')}) format('truetype');
        }
        @font-face {
          font-family: 'Mulish-Bold';
          src: url(${require('../assets/fonts/Mulish-Bold.ttf')}) format('truetype');
        }
        @font-face {
          font-family: 'CircularStd-Book';
          src: url(${require('../assets/fonts/CircularStd-Book.otf')}) format('truetype');
        }
      `}</style>
   //Your JSX, or your main app level code
 </>

还有另一个步骤,在你的自定义webpack配置文件中,添加这些加载器,如果你没有,那么在你的父级,创建一个webpack.js文件-

你的webpack js应该是这样的

const getWebpackConfig = require('@nrwl/react/plugins/webpack');

function getCustomWebpackConfig(webpackConfig) {
  const config = getWebpackConfig(webpackConfig);
  const isProduction = webpackConfig.mode === 'production';

  if (!isProduction) {
    config.resolve.alias = {
      'react-native': 'react-native-web',
      'react-native-linear-gradient': 'react-native-web-linear-gradient',
      'react-native-localization': 'react-localization'
    };

    config.module.rules.push(
      {
        test: /\.ttf$/,
        loader: require.resolve('file-loader'),
        options: { esModule: false, name: 'static/media/[path][name].[ext]' },
      },
      {
        test: /\.otf$/,
        loader: require.resolve('file-loader'),
        options: { esModule: false, name: 'static/media/[path][name].[ext]' },
      },
      {
        test: /\.(js|jsx)$/,
        exclude: function (content) {
          return (
            /node_modules/.test(content) &&
            !/\/react-native-paper\//.test(content) &&
            !/\/react-native-vector-icons\//.test(content) &&
          
          );
        },
        use: {
          loader: require.resolve('@nrwl/web/src/utils/web-babel-loader.js'),
          options: {
            presets: [
              [
                '@nrwl/react/babel',
                {
                  runtime: 'automatic',
                  useBuiltIns: 'usage',
                },
              ],
            ],
            plugins: [
                ["module-resolver", {
                    "alias": {
                      "^react-native$": "react-native-web",
                      "react-native-linear-gradient": "react-native-web-linear-gradient",
                      "react-native-localization": "react-localization"
                    }
                  }]
            ],
          },
        },
      },
      
    );
  }

  return config;
}

module.exports = getCustomWebpackConfig;

您的babel加载器可能不同,但ttf和otf规则是重要的,需要添加。我使用这个与react原生的web功能。如果您的项目不需要别名,则可以删除别名。

感谢这个博客,它让我更好地理解了这个概念- https://blog.nrwl.io/step-by-step-guide-on-creating-a-monorepo-for-react-native-apps-using-nx-704753b6c70e


我的感觉是,如果你在你的网站上有本地的字体,你应该能够使用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>