Thu, Sep 6, 2018

React + Reduxアプリケーションプロジェクトのテンプレートを作る ― その5: Material-UIとWebフォント

React + Reduxアプリケーションプロジェクトのテンプレートを作る ― その5: Material-UIとWebフォント

ReactReduxを学ぶために、開発環境というかプロジェクトテンプレートをスクラッチから作っている。 (最終的な成果はGitHubに置いた。)

前回はCSS周りの処理系をセットアップした。

既成Reactコンポーネント

前回まででHTMLもCSSもReactコンポーネント単位で書けるようになったんだけど、実際、自分で1からコンポーネントを書くのは、特にデザインセンスがない人にとっては辛い。 かっこいいUIコンポーネントを作りたいならデザイナーの協力が必要だけど、個人の開発などそれができない状況も多い。

という問題を抱えた人たち向けなのかはわからないが、既成のReactコンポーネントセットが色々OSSで提供されている。


今回はこの中でも圧倒的に人気なMaterial-UIを導入する。

Material-UI

Material-UIは簡単に使える。 とりあえずコアパッケージをインストールする。

yarn add @material-ui/core

v1.4.1が入った。


あとはパッケージに入っている色々なコンポーネントをMaterial-UIのドキュメント見ながら使えばいいだけ。

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のローダ設定は以下のようなのを追加すればいい。

(前略)
   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のローダ設定は以下のようなのを追加すればいい。

(前略)
   module: {
     rules: [
(中略)
-      }
+      },
+      {
+        test: /\.(png|woff|woff2|eot|ttf|svg)$/,
+        include: [path.resolve(__dirname, 'node_modules')],
+        loader: 'file-loader',
+      },
     ],
   },
(後略)


で、ここにある通り、styled-componentsのinjectGlobalというAPIを使って、以下のようにフォントファイルを読み込む。

src/font.js:

import { injectGlobal } from 'styled-components';
import roboto300 from '../node_modules/typeface-roboto/files/roboto-latin-300.woff';

injectGlobal`
  /* 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');
  }
`;


あとはこれをどこかのJavaScriptでインポートしてやればいい。

src/index.jsx:

 import React from 'react';
 import ReactDOM from 'react-dom';
 import App from './components/App';
+import './fonts';

 const root = document.getElementById('root');

 if (root) {
   ReactDOM.render(
     <App />,
     root,
   );
 }


次回はようやくReduxを導入する。