如何在 Material UI 的 webpack 构建中包含 Roboto 字体?

Posted

技术标签:

【中文标题】如何在 Material UI 的 webpack 构建中包含 Roboto 字体?【英文标题】:How to include Roboto font in webpack build for Material UI? 【发布时间】:2017-03-15 16:04:00 【问题描述】:

对于基于 Material UI (React) 并使用 Webpack 构建的 progressive Web 应用程序,我如何正确包含 Roboto 字体以便应用程序执行不依赖于谷歌服务器和字体也可以离线 ?

installation page 只是引用了Google fonts page,但这显然会强制从 Google 服务器下载字体。

类似的 Material UI Issue 存在关于 Roboto 字体,但仍依赖 Google 提供字体文件。

我找到了 NPM package providing the Roboto font files,但我不确定如何包含这些文件,因为提供了很多样式和字体格式,并且 我不知道 Material UI 真正需要什么样式强>。此外,仅通过 @import 导入这些字体系列似乎有 performance issues。

那么,将 right Roboto 文件与我的应用程序捆绑在一起的简单而好的解决方案是什么?

【问题讨论】:

查看这个以获得简单的解决方案 - ***.com/a/61554849/984471 【参考方案1】:

对于简洁的 Material-UI / Create React App PWA,不需要所有变体 - 您只需要:

yarn add @fontsource/roboto

index.js

import "@fontsource/roboto/latin-400.css";
import "@fontsource/roboto/latin-500.css";

theme.js(可选,但看起来干净利落)

overrides: 
  MuiCssBaseline: 
   html: 
    "-webkit-font-smoothing": "antialiased",
    "-moz-osx-font-smoothing": "grayscale",
    height: "100%",
    width: "100%"
  
 

您的字体将被捆绑并立即在线/离线使用

Demo

【讨论】:

【参考方案2】:

这就是我的团队在我们的 Webpack 项目中包含 Roboto 字体的方式:

下载 Roboto 字体并在字体特定文件夹中制作 CSS 文件

创建一个文件夹 (/fonts)。 从Font Squirrel 下载所有Roboto 字体。转到Webfont Kit标签,然后按下载@font-face Kit按钮并使用默认设置。 将字体移至/fonts。 创建 CSS 文件 (/fonts/index.css)。我们从this tutorial 获得了这个文件的内容。

index.css:

* 
  font-family: Roboto, sans-serif;  


@font-face 
    font-family: 'Roboto';
    src: url('Roboto-Regular-webfont.eot');
    src: url('Roboto-Regular-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-Regular-webfont.woff') format('woff'),
         url('Roboto-Regular-webfont.ttf') format('truetype'),
         url('Roboto-Regular-webfont.svg#RobotoRegular') format('svg');
    font-weight: normal;
    font-style: normal;

 
@font-face 
    font-family: 'Roboto';
    src: url('Roboto-Italic-webfont.eot');
    src: url('Roboto-Italic-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-Italic-webfont.woff') format('woff'),
         url('Roboto-Italic-webfont.ttf') format('truetype'),
         url('Roboto-Italic-webfont.svg#RobotoItalic') format('svg');
    font-weight: normal;
    font-style: italic;

 
@font-face 
    font-family: 'Roboto';
    src: url('Roboto-Bold-webfont.eot');
    src: url('Roboto-Bold-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-Bold-webfont.woff') format('woff'),
         url('Roboto-Bold-webfont.ttf') format('truetype'),
         url('Roboto-Bold-webfont.svg#RobotoBold') format('svg');
    font-weight: bold;
    font-style: normal;

 
@font-face 
    font-family: 'Roboto';
    src: url('Roboto-BoldItalic-webfont.eot');
    src: url('Roboto-BoldItalic-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-BoldItalic-webfont.woff') format('woff'),
         url('Roboto-BoldItalic-webfont.ttf') format('truetype'),
         url('Roboto-BoldItalic-webfont.svg#RobotoBoldItalic') format('svg');
    font-weight: bold;
    font-style: italic;

 
@font-face 
    font-family: 'Roboto';
    src: url('Roboto-Thin-webfont.eot');
    src: url('Roboto-Thin-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-Thin-webfont.woff') format('woff'),
         url('Roboto-Thin-webfont.ttf') format('truetype'),
         url('Roboto-Thin-webfont.svg#RobotoThin') format('svg');
    font-weight: 200;
    font-style: normal;

 
@font-face 
    font-family: 'Roboto';
    src: url('Roboto-ThinItalic-webfont.eot');
    src: url('Roboto-ThinItalic-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-ThinItalic-webfont.woff') format('woff'),
         url('Roboto-ThinItalic-webfont.ttf') format('truetype'),
         url('Roboto-ThinItalic-webfont.svg#RobotoThinItalic') format('svg'); (under the Apache Software License). 
    font-weight: 200;
    font-style: italic;

 
@font-face 
    font-family: 'Roboto';
    src: url('Roboto-Light-webfont.eot');
    src: url('Roboto-Light-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-Light-webfont.woff') format('woff'),
         url('Roboto-Light-webfont.ttf') format('truetype'),
         url('Roboto-Light-webfont.svg#RobotoLight') format('svg');
    font-weight: 100;
    font-style: normal;

 
@font-face 
    font-family: 'Roboto';
    src: url('Roboto-LightItalic-webfont.eot');
    src: url('Roboto-LightItalic-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-LightItalic-webfont.woff') format('woff'),
         url('Roboto-LightItalic-webfont.ttf') format('truetype'),
         url('Roboto-LightItalic-webfont.svg#RobotoLightItalic') format('svg');
    font-weight: 100;
    font-style: italic;

 
@font-face 
    font-family: 'Roboto';
    src: url('Roboto-Medium-webfont.eot');
    src: url('Roboto-Medium-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-Medium-webfont.woff') format('woff'),
         url('Roboto-Medium-webfont.ttf') format('truetype'),
         url('Roboto-Medium-webfont.svg#RobotoMedium') format('svg');
    font-weight: 300;
    font-style: normal;

 
@font-face 
    font-family: 'Roboto';
    src: url('Roboto-MediumItalic-webfont.eot');
    src: url('Roboto-MediumItalic-webfont.eot?#iefix') format('embedded-opentype'),
         url('Roboto-MediumItalic-webfont.woff') format('woff'),
         url('Roboto-MediumItalic-webfont.ttf') format('truetype'),
         url('Roboto-MediumItalic-webfont.svg#RobotoMediumItalic') format('svg');
    font-weight: 300;
    font-style: italic;

使用 file-loader webpack 模块加载字体文件,以便 webpack 能够识别它们

npm install --save file-loader (https://www.npmjs.com/package/file-loader) 在你的 webpack 配置中,像这样使用加载器:

webpack.conf.js:

loaders: [
  ..., 
    test: /\.(woff|woff2|eot|ttf|svg)$/,
    loader: 'file-loader',
    options:  name: '[name].[ext]', outputPath: 'fonts/', 
  ,
  ...
]

在应用主入口导入字体css文件

App.js:

import './fonts/index.css';

就是这样。您的应用程序的默认字体现在应该是 Roboto。

编辑:Material-UI 实际使用哪些 Roboto 字体?

这个问题的一部分是确定要包含在项目中的 正确 Roboto 字体,因为整个 Roboto 字体几乎是 5MB。

在README 中,包含Roboto 的说明指向:fonts.google.com/?selection.family=Roboto:300,400,500。在这里,300 = Roboto-Light,400 = Roboto-Regular,500 = Roboto-Medium。这些对应于typography.js file 中定义的字体粗细。虽然这三种字体粗细几乎占整个库的使用情况,但在 DateDisplay.js 中有一个对 Regular-Bold 的引用。如果你不使用 DatePicker,你应该可以安全地忽略它。除了 GitHub markdown 样式之外,项目中的任何地方都没有使用斜体字体样式。

此信息在撰写本文时是准确的,但将来可能会发生变化。

【讨论】:

谢谢。是的,这有效。但问题是,我正在创建一个PWA,这意味着 all 资产会被下载和缓存。仅字体文件就总计 4,5 兆字节。我猜(希望)MUI 并不真正需要所有样式(薄、轻、中、...) - 但如何找出...? 啊,我现在看到了这个问题。我不知道除了 Roboto-Regular 之外您还需要任何其他字体。这取决于是否有任何组件使用font-weightfont-style 样式。今晚我将尝试验证这一点。无论如何,我找到了an article about lazy loading fonts for performance gain。你能预先加载 Roboto-Regular 并稍后延迟加载其他变体吗? 有趣的文章。但是,由于这是一个 PWA,我需要让所有字体文件都可以离线使用(这意味着必须下载它们)。我想没有其他方法可以删除不需要的样式(从而确定哪些是不必要的) 现在将“loader: 'file?name=fonts/[name].[ext]'”行替换为 loader:" 'file-loader?name=fonts/[name].[ext] ]' " 您能否将我们需要访问该网站的 fontsquirrel 添加到您的 tut 中,然后转到 Webfont kit 选项卡,然后使用默认设置按 Download @font-face kit 按钮?这似乎并不明显。此外,对于最后一个 webpack,您需要提供:` test: /\.(woff|woff2|eot|ttf|svg)$/, loader: 'file-loader', options: name: '[name] .[ext]', outputPath: 'fonts/', , ,` 否则效果很好。【参考方案3】:

我尝试使用 npm 安装 typeface-roboto,但没有成功。此外,使用材料 ui 中的 CDN 也不起作用。但是,使用 npm 安装 webfontloader 是可行的。这是解决方案, 首先,

npm install webfontloader --save

然后,在您的 entry.js 文件中从 webfontloader 导入 WebFont,例如 App.js 或 index.js

import WebFont from "webfontloader";
WebFont.load(google: families: ["Roboto:300,400,500"]);

【讨论】:

解决无数其他问题的唯一解决方案。导入必须在入口点 javascript 文件中【参考方案4】:

如果您确实使用 Angular,而 import 'typeface-roboto' 并不理想和简单,您可能会使用与此处建议的方式稍有不同。

首先,按照其他人的描述安装这个不错的 npm 包:

npm install typeface-roboto --save

然后将其添加到您的angular.json

"styles": [
  "node_modules/typeface-roboto/index.css",
  [...],
  "src/styles.css"
],

【讨论】:

致投反对票的人:您能否解释一下为什么您投反对票而不是点击“投反对票”?【参考方案5】:

您也可以像此问题中记录的那样进行操作: https://github.com/callemall/material-ui/issues/6256

npm install typeface-roboto --save

然后,在你的 index.js 中:

import 'typeface-roboto'

适用于 webpack/create-react-app。

【讨论】:

也适用于 Gatsby! 那是因为上述项目提供了开箱即用的字体支持。 OP 询问如何在“弹出”或手动 webpack 模式下设置字体 @kimomat 您能否提示如何使用import typeface-roboto 指定要导入的确切字体?例如,如果我只想要 300 和 400 种字体。 据我所知,这个 npm 包包括所有字体粗细。查看 git 存储库:github.com/KyleAMathews/typefaces/blob/master/packages/roboto/… 这是否意味着应用中的所有文本都将采用roboto字体,还是还有更多工作要做?【参考方案6】:

如果应用程序是使用 create-react-app 启动的,它没有 [可见的] webpack 配置文件。在这种情况下,您可以执行以下操作:

    在 /public 中创建 /fonts 目录

    创建/public/fonts/fonts.css,定义@font-faces

    @font-face font-family: 'inglobal'; font-weight: normal; font-style: normal; src: url('./OperatorMono.ttf');

    复制字体文件

    添加 <link rel="stylesheet" href="%PUBLIC_URL%/fonts/fonts.css"> 到/public/index.html的

    万岁!

5/b。如果出于任何原因,它仍然不起作用,请将字体的扩展名更改为 .css(也在 src: url('./OperatorMono.css') )

【讨论】:

我不是 Webpack 方面的专家,但我认为你不应该添加加载 CSS 的 HTML 标签,webpack 会处理它作为优化的一部分,所以我认为你正在绕过网页包。 是的,绕过是重点,因为你不能修改 webpack 配置文件——除非它被不可逆转地弹出。

以上是关于如何在 Material UI 的 webpack 构建中包含 Roboto 字体?的主要内容,如果未能解决你的问题,请参考以下文章

TypeError: (0 , _material_ui_core__WEBPACK_IMPORTED_MODULE_3__.makeStyles) 不是函数

找不到模块'@ material-ui / core'

react__WEBPACK_IMPORTED_MODULE_0___default.a.useContext 不是函数——在 Material UI 中使用自动完成时

无法解析模块 - Material-UI

从库导入的 React 组件的 Material-Ui 主题化问题

ReactJS + Material-UI:如何在每个 TableRow 中使用 Material-UI 的 FlatButton 和 Dialog?