React + Reduxアプリケーションプロジェクトのテンプレートを作る ― その5: Material-UIとWebフォント
Thu, Sep 6, 2018
react frontend material-uiTable of Contents
ReactとReduxを学ぶために、開発環境というかプロジェクトテンプレートをスクラッチから作っている。 (最終的な成果はGitHubに置いた。)
前回はCSS周りの処理系をセットアップした。
(2020/4/29更新)
既成Reactコンポーネント
前回まででHTMLもCSSもReactコンポーネント単位で書けるようになったんだけど、実際、自分で1からコンポーネントを書くのは、特にデザインセンスがない人にとっては辛い。 かっこいいUIコンポーネントを作りたいならデザイナーの協力が必要だけど、個人の開発などそれができない状況も多い。
という問題を抱えた人たち向けなのかはわからないが、既成のReactコンポーネントセットが色々OSSで提供されている。
- Material-UI: GoogleのマテリアルデザインのReact実装。
- Semantic UI React: Semantic UIのReactバインディング。
- antd: Ant DesignのReact実装。
- Blueprint: 複雑でデータ量の多いUI向けに作られたReact UIツールキット。
- React-Bootstrap: BootstrapのReactバインディング。現時点ではv4未対応。
- Grommet: HPEによるエンタープライズレディなデザインシステム。
- Fluent UI (旧Office UI Fabric React): OfficeなどのMicrosoft製品に使われているReactコンポーネントセット。
今回はこの中でも圧倒的に人気なMaterial-UIを導入する。
Material-UI
Material-UIは簡単に使える。 とりあえずコアパッケージをインストールする。
$ yarn add @material-ui/core
v3.5.1が入った。
あとはパッケージに入っている色々なコンポーネントをMaterial-UIのドキュメント見ながら使えばいいだけ。
src/components/App.jsx
:
import React from 'react';
import styled from 'styled-components';
+import Button from '@material-ui/core/Button';
const Wrapper = styled.div`
font-size: 5rem;
`;
const App = () => (
<Wrapper>
- HOGE
+ <Button variant="contained">
+ HOGE
+ </Button>
</Wrapper>
);
export default App;
これでただのテキストがボタンになった。
CSS Web Fonts
前節でいちおうMaterial-UI使えたけど、フォントをケアしてやるともう少しかっこよくなる。 Material-UIはRobotoフォントを想定して作られているが、これはブラウザにデフォルトで入ってはいないので、そのままだとArialとかにフォールバックされちゃう。 のでRobotoフォントを導入する。
フォントはCSS Web Fontsの機能である@font-faceで、フォントファイルをブラウザにロードさせることで導入できる。
@font-face
で読み込むフォントファイル(i.e. url()
関数で指定するファイル)はwebpackでバンドルできる。
Robotoフォントのフォントファイルはnpmで配布されていて、Yarnでプロジェクトにインストールできる。
$ yarn add typeface-roboto
フォントファイルの種類は、OTFとかTTFとかWOFFとかWOFF2とかいろいろあるけど、この記事などをみるに、WOFFだけ使えばよさげ。
フォントファイルのバンドルはurl-loaderを使う方法とfile-loaderを使う方法とがある。
url-loaderを使う方法
url-loaderを使う場合は、url-loaderとフォールバック用のfile-loaderをインストールする。
$ yarn add -D url-loader file-loader
webpackのローダ設定は以下のようなのを追加すればいい。
webpack.common.js
:
(前略)
module: {
rules: [
(中略)
- }
+ },
+ {
+ test: /\.(png|woff|woff2|eot|ttf|svg)$/,
+ include: [path.resolve(__dirname, 'node_modules/typeface-roboto')],
+ loader: 'url-loader',
+ options: {
+ limit: 100000,
+ },
+ },
],
},
(後略)
あとは、typeface-robotoパッケージ内のフォントファイルを指すようにCSSに@font-faceを書けばいい。 例えば、weightが300のWOFFファイルを読むなら以下のような感じ。
src/fonts.css
:
@font-face {
font-family: 'Roboto';
font-style: normal;
font-display: swap;
font-weight: 300;
src: local('Roboto Light'), local('Roboto-Light'),
url('../node_modules/typeface-roboto/files/roboto-latin-300.woff') format('woff');
}
これをどこかのJavaScriptでインポートしてやればいい。
src/index.jsx
:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
+import './fonts.css';
const root = document.getElementById('root');
if (root) {
ReactDOM.render(
<App />,
root,
);
}
けど、styled-componentsを使っている場合はurl-loaderは使えないみたいで、代わりにfile-loaderを使う必要がある。
file-loaderを使う方法 (styled-components)
file-loaderを使う場合は、file-loaderだけインストールすればいい。
$ yarn add -D file-loader
webpackのローダ設定は以下のようなのを追加すればいい。
webpack.common.js
:
(前略)
module: {
rules: [
(中略)
- }
+ },
+ {
+ test: /\.(png|woff|woff2|eot|ttf|svg)$/,
+ include: [path.resolve(__dirname, 'node_modules')],
+ loader: 'file-loader',
+ },
],
},
(後略)
で、ここを参考にしてフォントファイルを読みこむ。injectGlobalというstyled-componentsのAPIを使えとあるけど、injectGlobalはstyled-components v4でcreateGlobalStyleに代わったので、以下のように書く。
src/fonts.js
:
import { createGlobalStyle } from 'styled-components';
import roboto300 from '../node_modules/typeface-roboto/files/roboto-latin-300.woff';
const Fonts = createGlobalStyle`
/* roboto-300normal - latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-display: swap;
font-weight: 300;
src:
local('Roboto Light'),
local('Roboto-Light'),
url('${roboto300}') format('woff');
}
`;
export default Fonts;
ここでexportされるFonts
はReactコンポーネントになっているので、それをどこかのJSXに追加してやればいい。
src/components/App.jsx
:
import React from 'react';
import styled from 'styled-components';
import Button from '@material-ui/core/Button';
+import Fonts from '../fonts';
const Wrapper = styled.div`
font-size: 5rem;
`;
const App = () => (
<Wrapper>
<Button variant="contained">
HOGE
</Button>
+ <Fonts />
</Wrapper>
);
export default App;
次回はようやくReduxを導入する。