Как добавить шрифты в проекты, основанные на создании-реакции-приложения?


177

Я использую приложение create-реагировать и предпочитаю не eject.

Непонятно, куда должны идти шрифты, импортированные через @ 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');
}

2
Вы проверили раздел «Добавление шрифтов» в Руководстве пользователя?
Дан Абрамов

2
@DanAbramov У меня есть, рекомендуется импортировать шрифт. Но я чувствую, что не ясно (по крайней мере, мне) о том, как это должно быть сделано на практике. В то же время я сделал это gist.github.com/maximveksler/5b4f80c5ded20237c3deebc82a31dcd5, и это, кажется, работает (оповещения веб-пакета, если он не может найти файл шрифта), но я уверен, что это не оптимальное решение и пример или если это будет задокументировано, это поможет. Ты за то, что обратился!
Максим Векслер

2
Я ответил. Ваш подход выглядит неправильно для меня: %PUBLIC_URL%не может работать (и не нужен) в файле CSS. Кроме того, как описано в руководстве, вы должны использовать импорт JS почти во всех случаях, а не в общей папке.
Дан Абрамов

Существует ли какая-либо утилита / пакет для сканирования указанной папки на наличие шрифтов и создания файла сценария со всеми вариантами шрифтов?
Утомительно

Ответы:


291

Есть два варианта:

Использование импорта

Это предлагаемый вариант. Это гарантирует, что ваши шрифты пройдут через конвейер сборки, получат хэши во время компиляции, чтобы кеширование браузера работало правильно, и чтобы вы получали ошибки компиляции, если файлы отсутствуют.

Как описано в разделе «Добавление изображений, шрифтов и файлов» , вам необходимо импортировать файл CSS из JS. Например, по умолчанию 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');
}

Обратите внимание, как мы используем относительный путь, начиная с ./. Это специальная запись, которая помогает конвейеру сборки (на основе Webpack) обнаружить этот файл.

Обычно этого должно быть достаточно.

Использование publicпапки

Если по какой-то причине вы предпочитаете не использовать конвейер сборки, а вместо этого делаете это «классическим способом», вы можете использовать publicпапку и поместить туда свои шрифты.

Недостатком этого подхода является то, что файлы не получают хэши при компиляции для производства, поэтому вам придется обновлять их имена каждый раз, когда вы меняете их, иначе браузеры будут кэшировать старые версии.

Если вы хотите сделать это таким образом, поместите шрифты в publicпапку, например, в public/fonts/MyFont.woff. Если вы следуете этому подходу, вы должны также поместить CSS-файлы в publicпапку и не импортировать их из 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');
}

Обратите внимание, как я использую fonts/MyFont.woffв качестве пути. Это связано с тем, что он index.cssнаходится в publicпапке, поэтому он будет обслуживаться по общедоступному пути (обычно это корневой каталог сервера, но если вы развернете на GitHub Pages и установите свое homepageполе на http://myuser.github.io/myproject, оно будет обслуживаться из /myproject). Однако fontsтакже есть в publicпапке, поэтому они будут обслуживаться fontsотносительно (либо, http://mywebsite.com/fontsлибо http://myuser.github.io/myproject/fonts). Поэтому мы используем относительный путь.

Обратите внимание, что поскольку в этом примере мы избегаем конвейера сборки, он не проверяет, существует ли файл на самом деле. Вот почему я не рекомендую такой подход. Другая проблема заключается в том, что наш index.cssфайл не минимизируется и не получает хэш. Таким образом, это будет медленнее для конечных пользователей, и вы рискуете, что браузеры кешируют старые версии файла.

 Какой способ использовать?

Перейти с первым методом («Использование импорта»). Я описал только второй, поскольку именно это вы и пытались сделать (судя по вашему комментарию), но у него много проблем, и он должен быть последним средством, когда вы работаете над какой-то проблемой.


5
пример в документах был бы полезен, я также был немного смущен
Том

2
Я обнаружил, что мне действительно нужно использовать URL ./fonts/Myfont.woff, а не ./Myfont.woff
th3morg

57
Если кто-то добавляет ttfшрифт, вы должны указать truetypeвместо * в ttfкачестве параметра format* .
milkersarac

3
@milkersarac ты самый лучший!
Жоао Виласа

19
После @milkersarac, если вы используете, otfвам нужно поставить opentype.
Карл Тейлор

46

Вот несколько способов сделать это:

1. Импорт шрифта

Например, для использования Roboto установите пакет, используя

yarn add typeface-roboto

или

npm install typeface-roboto --save

В index.js:

import "typeface-roboto";

Есть пакеты npm для многих шрифтов с открытым исходным кодом и большинства шрифтов Google. Вы можете увидеть все шрифты здесь . Все пакеты из этого проекта .

2. Для шрифтов, размещенных третьей стороной

Например, Google шрифты, вы можете перейти на fonts.google.com, где вы можете найти ссылки, которые вы можете поместить в свойpublic/index.html

снимок экрана fonts.google.com

Это будет как

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

или

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

3. Загрузка шрифта и добавление его в исходный код.

Скачать шрифт Например, для шрифтов Google вы можете перейти на fonts.google.com . Нажмите на кнопку загрузки, чтобы загрузить шрифт.

Переместить шрифт в fontsкаталог в вашем 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

или

npm install webfontloader --save

В src/index.js, вы можете импортировать это и указать необходимые шрифты

import WebFont from 'webfontloader';

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

2
--save по умолчанию с npm 5 (2017)
NattyC

Спасибо за комментарий @Natalie, я рад, что npm сделал это изменение.
sudo bangbang

@sudobangbang Спасибо, решение № 3 сработало для меня. Тем не менее, есть ли способ не поместить fontsпапку под src, а под publicвместо? Я попробовал, но, похоже, не позволил ...
Йосси Вайнштейн

@YossiVainshtein, я так не думаю. Поскольку вы используете шрифты в App.css, он также должен быть скомпилирован с ним.
Судо Бэнгбэнг

For ttf format, you have to mention format('truetype'). For woff, format('woff')сделал это для меня! Спасибо!
Джозеф Бриггс

7
  1. Перейдите в Google Fonts https://fonts.google.com/.
  2. Выберите ваш шрифт, как показано на рисунке ниже:

введите описание изображения здесь

  1. Скопируйте, а затем вставьте этот 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>

Результат:

введите описание изображения здесь


1
Во многих случаях (например, в корпоративных сетях) доступ к внешнему CDN блокируется брандмауэром, и этот метод, хотя и правильный, может не работать. У нас есть несколько сетей VLAN в нашей организации, и, за исключением ИТ и немногих других, все сети VLAN блокируют внешний доступ к CDN, что также означает, что контент CDN Google также блокируется. Был там, сделал это.
AnBisw

2

Вы можете использовать модуль WebFont , который значительно упрощает процесс.

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

0

Я делал такие ошибки.

@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);

0

Я потратил все утро на решение аналогичной проблемы после того, как попал в этот вопрос. Я использовал первое решение Дэна в ответе выше в качестве отправной точки.

проблема

У меня есть разработчик (это на моей локальной машине), подготовка и производственная среда. Мои промежуточные и производственные среды живут на одном сервере.

Приложение развернуто в промежуточной acmeserver/~staging/note-taking-appверсии, а рабочая версия работает acmeserver/note-taking-app(обвините ИТ).

Все медиа-файлы, такие как шрифты, прекрасно загружались в dev (то есть react-scripts start).

Однако, когда я создавал и загружал промежуточные и производственные сборки, .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/css/когда файл шрифта просто живет в/static/media/ а также дублирует папку назначения. Я исключил конфиг сервера, являющийся виновником.

RefererОтчасти по вине тоже.

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

Для package.jsonфайла установлено homepageсвойство ./note-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"
  }
  //...
}

Решение

Это было долго, но решение состоит в том, чтобы:

  1. изменить PUBLIC_URL переменную env в зависимости от среды
  2. удалить homepageсвойство из package.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");
}

Материал для чтения

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.