1年後に差がつくFont Awesome5 ～フロントエンド開発(ES6,Webpack4,Babel7)への導入～

# 概要
**[Font Awesome](https://fontawesome.com/icons?d=gallery&m=free)**(フォントオーサム)はFreeで使えるアイコン集で、このジャンルでほぼデファクトといって良い存在になっています。Free版とPro版がありますが**Free版**でも約**1500種類**のアイコンが使えます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/3022227c-a24a-1546-3c83-250e571f6d50.png)
本稿では、node.js環境での開発を前提としたWebフロントエンド開発で [Font Awesome5](https://fontawesome.com/start) を使う時のポイントを説明します。Font Awesomeはv5になってフロントエンド開発との連携機能が大幅強化され、お手軽にJavaScriptのバンドルにフォントを埋め込むことができます。

Font Awesomeのアイコンを使う（バンドルする）には以下の3ステップを踏みます。

- Font Awesome を npm でインストールして、
- JavaScriptのコードで必要なアイコンだけを import して
- Font Awesomeの必要最小限が含まれるように webpack でバンドルする

最終的には、1つのbundle.jsの中に、そのアプリで使いたいアイコンだけが取り込まれた状態にします。
つまり、アイコンデータもすべてbundle.jsに入るので、HTML上でCSSを指定する必要も無いし、また必要なアイコンだけ取り込むのでbundle.jsのサイズも最小限にできます

<font color=red>ハマりポイント</font>（例：minimizer(uglify-js)によっては Font Awesome含むビルドが重い！エラい時間がかかる！）もあるので、そこも扱います。

## 想定読者
- Font Awesomeを使ったことがない、または、JSにバンドルする方式では使ったことがない人
- **npm**や**webpack**は使ったことがある人

## 対象環境
- **npm**、**Webpack4**、**ES6**、**Babel7**
- Font Awesomeは **Font Awesome v 5.＊** の**Free版**を対象にします
- 特定のフレームワーク(Vue/React/Angular等)に特化した内容は扱いませんが知識は応用可能です

## ソースコード
記事で使用した全ソースコードはこちらにあります
https://github.com/riversun/font-awesome5-js-example

# (1)CDNを使って表示する

どんなアイコンがあるかは https://fontawesome.com/icons?d=gallery&m=free からさがせる。

まずは、インストール不要でHTMLで直接CDNを参照して表示する方法から。

以下のようにするだけで、犬とコメントと猫のアイコンが表示される。

```html:index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"
          integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<body>
<i class="fas fa-dog fa-3x"></i>
<i class="far fa-comments fa-3x"></i>
<i class="fas fa-cat fa-3x fa-flip-horizontal"></i>
</body>
</html>
```

**表示結果**

![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/f4157ed2-3582-272d-055e-e464bde40399.png)

ある意味一番簡単な方法で、

```html
 <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"
          integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
```

Font AwesomeのCSSを直接CDNから読み込み、

```html
<i class="fas fa-dog fa-3x"></i>
```

のように`<i>タグ`の**class**に **fas fa-dog fa-3x** とクラスを指定するだけで美しいフォントが表示されます。

「おーさむ！」となる。

## SolidスタイルとRegularスタイル→Font Awesomeのフォントスタイル
[ここ](https://fontawesome.com/icons?d=gallery)をみるとFont Awesomeには大量のアイコンがあることがわかるが、フォントのスタイルは4種類に分類される。

- **Solid**スタイル・・・中が塗りつぶされているアイコン![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/55f24129-56fa-ecc4-a86d-1ba73deb1ce9.png)  
Solidスタイルには**fas**というクラスを指定する

```html:Solidスタイルの例
<i class="fas fa-arrow-circle-up"></i>
```

- **Regular**スタイル・・・線画で表現されたアイコン![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/6d246972-376a-f4c1-b59c-dcf9df51873c.png)  
Regularスタイルには**far**というクラスを指定する

```html:Regularスタイルの例
<i class="far fa-arrow-circle-up"></i>
```

- **Brands**スタイル・・・ブランドのアイコン ![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/ee02dfb3-13b7-122c-b752-482de140db11.png)  
Brandsスタイルには**fab**というクラスを指定する

```html:Brandsスタイルの例
<i class="fab fa-apple"></i>
```

**Light**スタイル・・・細い線で表現されたアイコン。PRO版のみ。

このようにHTMLにCSSを記載して、`<i>タグ`で指定する方法が一番簡単だしとっつきやすい。
次章以降は、本稿の目的である、JSにバンドルしてFont Awesomeを使う方法を見る。

# (2)ライブラリ版をつかって表示する

ここからが本編、Font Awesomeをインストールしていく。

まずJavaScriptで使えるFont Awesomeのパッケージだが、大きく2種類ある

便宜的に**基本パッケージ版(Basic packages)**と**SVGコア版(fontawesome-svg-core)**という呼び方をするが、前者は手軽かつすぐに使えることを目的とした全部入りのパッケージ、後者はたとえば使いたいアイコンだけを選んだり、挙動を詳細に制御したりできるのが特徴。どちらもJSにバンドルすることができるので、Font Awesomeのアイコンがバンドルされた app.js を作成することができる。

**2つのパッケージの目的**

<table>
<tr><td></td><td>名称</td><td>npmパッケージ名</td><td>目的</td></tr>
<tr><td>基本パッケージ版</td><td>Font Awesome<br> (JavaScript)</td><td><span>@</span>fortawesome/fontawesome-free <br>(※1)</td><td>すぐに使えること</td></tr>
<tr><td>SVGコア版</td><td>Font Awesome SVG Core<br> (JavaScript)</td><td><span>@</span>fontawesome-svg-core <br>(※2)</td><td>APIで詳細に制御できること</td></tr>
</table>

※1 有償版の<span>@</span>fortawesome/fontawesome-proもある
※2 スタイルごとのパッケージもある（後半で説明する)

公式の解説は[こちら](https://fontawesome.com/how-to-use/on-the-web/advanced/svg-javascript-core)



# (2)-1基本パッケージ版 Font Awesome (JavaScript) のインストールと実行

まず、基本パッケージ版からみていく。

## インストール

**@fortawesome/fontawesome-free**パッケージをnpm installする

```shell
npm install @fortawesome/fontawesome-free --save
```

package.jsonは以下のようになる

```json:package.json(抜粋)
  "dependencies": {
    "@fortawesome/fontawesome-free": "^5.6.3"
  }
```

## コーディング

インストールされた **@fortawesome/fontawesome-free**パッケージから必要なモジュールインポートする
**Solid**タイプと**Regular**タイプを使いたいので以下のようにする。HTML内に`<i>タグ`で記述したブラウザに表示したいだけなので、コードはこのimport文だけでOK。

```index.js
import '@fortawesome/fontawesome-free/js/fontawesome';
import '@fortawesome/fontawesome-free/js/solid';
import '@fortawesome/fontawesome-free/js/regular';
```

htmlは以下のようにする。`<i>タグ`を使って記述する部分は、CDNからCSSを参照する場合とおなじ。
違いはCSSファイルをインポートするかわりに**<script>**でバンドル(**app.js**)を読み込む部分。

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>I love fontawesome</title>
</head>
<body>
<i class="fas fa-dog fa-3x"></i>
<i class="far fa-comments fa-3x"></i>
<i class="fas fa-cat fa-3x fa-flip-horizontal"></i>
<script src="js/app.js"></script>
</body>
</html>
```

ビルドするにあたっては以下のような**package.json**と**webpack.config.js**を用意する。
```npm start```でブラウザで確認できるようにするのと```npm run build```でリリース用のバンドルを生成できるようにする。

```json:package.json
{
  "name": "bundle-font-awesome",
  "version": "1.0.0",
  "description": "How to bundle font-awesome",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server",
    "build": "webpack --config webpack.config.js --mode production"
  },
  "devDependencies": {
    "webpack": "^4.19.1",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.11"
  },
  "dependencies": {
    "@fortawesome/fontawesome-free": "^5.6.3"
  }
}
```

```js:webpack.config.js
const path = require('path');
module.exports = (env, argv) => {
    const conf = {
        mode: 'development',
        devServer: {
            open: true,
            contentBase: path.join(__dirname, 'public'),
        },
        entry: {app: './src/index.js'},
        output: {
            path: path.join(__dirname, 'dist'),
            publicPath: '/js/',
            filename: '[name].js',
            libraryTarget: 'umd'
        }
    };
    return conf;
};
```

## ブラウザで確認する

```shell
npm start
```

**表示結果**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/77705b34-f757-33d3-3a22-f1e93f6dc29f.png)

このようにバンドル(**app.js**)を読み込んで、htmlには以下のように

```html
<i class="fas fa-dog fa-3x"></i>
<i class="far fa-comments fa-3x"></i>
<i class="fas fa-cat fa-3x fa-flip-horizontal"></i>
```

と普通にタグを書いておいただけなのにキチンと表示されるのは、**@fortawesome/fontawesome-free**ライブラリががんばっているから。

何をどうがんばっているかというと、以下のことをやってくれる  

　1. ページ内にある```<i>```タグを検出して、```<i>```タグ→```<svg>```タグ(アイコンのベクターイメージ)に自動変換
　2. ページ内のアイコンの追加や変更の自動監視

基本パッケージのこのような便利機能によって、うまくアイコンが表示される。


## バンドルをビルドする

表示が確認できたところで、次にバンドル(app.js)を生成する。
以下のようにproduction用ビルドをしてバンドル(app.js)の生成がどのようになるか見てみる。

```shell:production用ビルドを実行する
npm run build
```

```shell:ビルド結果
Hash: 4181e1ed417c819468de
Version: webpack 4.28.4
Time: 1884ms
Built at: 2019-01-14 11:50:32
 Asset     Size  Chunks                    Chunk Names
app.js  679 KiB       0  [emitted]  [big]  app
Entrypoint app [big] = app.js
[0] ./src/index.js 154 bytes {0} [built]
    + 3 hidden modules
```

app.jsが生成される。全部入りの基本パッケージ版を入れるとapp.jsは <font color=red>**679 KiB**</font>となる。この例の場合で考えると<font color=red>使いたいアイコンが3種類だけなのにバンドルはアイコン全部入りになってしまうのでサイズが大きい。</font>導入は簡単だが、基本パッケージ版ライブラリを取り込むとこのくらいのサイズを覚悟する必要がある。

まとめると↓のようになる。

<table>
<tr><td>ライブラリ</td><td>バンドル対象</td><td>インポート方法</td><td>Webpack4<br>Minimizer</td><td>ビルド時間</td><td>サイズ</td></tr>
<tr><td>基本パッケージ版</td><td>すべてのアイコン</td><td>インポート</td><td>Default(terser)</td><td>1.8s</td><td>679KiB</td></tr>
</table>

### 本章のソースコード
https://github.com/riversun/font-awesome5-js-example/tree/master/step01_basic

# (2)-2 SVGコア版Font Awesome SVG Core (JavaScript)のインストールと実行

次は、**SVGコア版**をつかう。

## インストール

**SVGコア版**のパッケージ**@fortawesome/fontawesome-svg-core**をインストールする。

```shell:コマンドライン
npm install @fortawesome/fontawesome-svg-core
```

今インストールしたのはAPIとロジックが中心のライブラリなので、追加でSolidスタイルとRegularスタイルのアイコンデータが入っているパッケージもインストールする

```shell:コマンドライン
npm install @fortawesome/free-solid-svg-icons
npm install @fortawesome/free-regular-svg-icons
```

すると、package.jsonは↓のようになる。
**SVGコア(svg-core)**のライブラリと、**Regular**スタイル、**Solid**スタイルのライブラリがそれぞれインストールされた状態となる。

```json:package.json(抜粋)
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.12",
    "@fortawesome/free-regular-svg-icons": "^5.6.3",
    "@fortawesome/free-solid-svg-icons": "^5.6.3"
  }
```

## コーディング

それでは、SVGコア版のコードを書いていく。

インストールした3つのパッケージ(svg-core,Solidスタイル,Regularスタイル)をそれぞれ**import**した後、**バンドルしたいアイコンのみ追加する**処理を記述する流れとなる。

```js:index.js
import {config, dom, library} from '@fortawesome/fontawesome-svg-core';
import {faDog, faCat} from '@fortawesome/free-solid-svg-icons';
import {faComments} from '@fortawesome/free-regular-svg-icons';

library.add(faDog,faComments,faCat);

dom.i2svg();
```

<hr>
さっそく、コードを順にみていく。

```js
import {config, dom, library} from '@fortawesome/fontawesome-svg-core';
```

ここでは、**@fortawesome/fontawesome-svg-core**から **config**,**dom**,**library**の3つのオブジェクトを取得している。

それぞれの役割は以下の通り。

- **config**・・・各種挙動の設定用コンフィギュレーションオブジェクト
- **dom**・・・DOM関連のユーティリティ
- **library**・・・取り込みたいアイコンを追加できるユーティリティ

<hr>

```js
import {faDog, faCat} from '@fortawesome/free-solid-svg-icons';
import {faComments} from '@fortawesome/free-regular-svg-icons';
```

ここでは、**使いたいアイコンのみ**を **{ }**で指定した名前つきインポートをつかって指定する。

使いたいアイコンとして、
**Solid**スタイルのライブラリから**faDog**と**faCat**
**Regular**スタイルのライブラリから**faComments**を指定してインポートしている。

<hr>

```js
library.add(faDog,faComments,faCat);
```

**library.add**では、使いたいアイコンを追加する。いま上でインポートした3つのアイコンを利用したいので、**library.add**をつかってアイコンライブラリ（使用することを宣言するアイコンリスト）に追加する。

このように**指定したアイコンだけをインポートすることで、バンドルのサイズを最小限に押さえる**ことができる。

<hr>

```js
dom.i2svg();
```

[**dom.i2svg**](https://fontawesome.com/how-to-use/with-the-api/methods/dom-i2svg)はその名のとおり`<i>タグ`を`<svg>タグ`に変換するためのメソッドで、これを実行すると現在のDOMツリー上に存在する`<i>タグ`がアイコンに置き換わる。

### dom.i2svg()で描画されない場合

さて、DOM構築タイミングによっては**dom.i2svg**でアイコンが表示されない場合がある。
たとえば、以下のような場合はアイコンが表示されない。

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<script src="js/app.js"></script>
<i class="fas fa-dog fa-3x"></i>
<i class="far fa-comments fa-3x"></i>
<i class="fas fa-cat fa-3x fa-flip-horizontal"></i>
</body>
</html>
```

理由は**app.js**の読み込みよりも後に`<i>タグ`が定義されており、かつ現在のコードは**app.js**読み込み直後に**dom.i2svg**が実行しているため。**dom.i2svg**実行時点では`<i>タグ`が未定義となる。

**dom.i2svg**には要素の追加や変更を監視するような機能は無く実行時点のDOMツリーに対してのみ`<i>タグ`の変換を行うため。

この例の場合は、 `<script>タグ`の位置を`<i>タグ`定義より後に持ってくるというのが一般的な解だが、**要素の追加変更を監視できるAPI='[**dom.watch**](https://fontawesome.com/how-to-use/with-the-api/methods/dom-watch)'がある**のそちらを使う手もある。

### dom.watch() を使用してiタグをアイコンに自動置換

[**dom.i2svg**](https://fontawesome.com/how-to-use/with-the-api/methods/dom-i2svg)のかわり[**dom.watch**](https://fontawesome.com/how-to-use/with-the-api/methods/dom-watch)を使えば先ほどのようなパターンでも対応してくれる

```js:要素の追加や変更を監視してiタグをアイコンに置き換えてくれる
dom.watch();
```

### dom.i2svgのTIPS

ちょっともどるが、**dom.i2svg**にはいくつかオプションもあるので簡単にみてみる。


**具体的にDOM要素を指定する**

↓のようにすると、iタグのsvgタグへの変換対象ノードを指定することができる

```js
dom.i2svg({ node: document.getElementById('example_element_id') })
```

**変換が終わったらコールバックを受け取る**

`<i>タグ`→`<svg>タグ`への変換が終了したときに呼び出されるコールバックを↓のように指定することもできる

```js
dom.i2svg({ callback: ()=>{}})
```

## config の使い方

さきほど↓のように **config**オブジェクトを取得したがこの使い方を簡単にみておく

```js
import {config, dom, library} from '@fortawesome/fontawesome-svg-core';
```

**config**を使うとFont Awesomeの挙動をカスタマイズすることができる。
このようにインポート時に**config**オブジェクトを取得できる。

以下のコード例でみてみる

```js:index.js(dogを追加していない状態)
import {config, dom, library} from '@fortawesome/fontawesome-svg-core';
import {faCat} from '@fortawesome/free-solid-svg-icons';
import {faComments} from '@fortawesome/free-regular-svg-icons';
library.add(faComments,faCat);
dom.i2svg();
```

上のコードでは、わざと**faCat**と**faComments**しかアイコンライブラリに追加していない状態で以下のHTMLのように`<i class="fas fa-dog fa-3x"></i>`で犬のアイコンを表示しようとするHTMLの例となる。

```html
<i class="fas fa-dog fa-3x"></i>
<i class="far fa-comments fa-3x"></i>
<i class="fas fa-cat fa-3x fa-flip-horizontal"></i>
```

```shell
npm start
```

**npm start**すると以下のように、**fa-dog**はJavaScriptのコードでインポートしなかったので、アイコンが見つからないときの？マークが表示される。

**表示結果**
![faa.gif](https://qiita-image-store.s3.amazonaws.com/0/170905/d8aa6655-6cc1-fd46-00e7-f85245807da1.gif)

**configを使うと、こうした場合の挙動を変更できる**
さっそく**config**をつかって挙動変更してみる。コードには以下のように **config.showMissingIcons = false;**を追加する

```js:index.js
import {config, dom, library} from '@fortawesome/fontawesome-svg-core';
import {faCat} from '@fortawesome/free-solid-svg-icons';
import {faComments} from '@fortawesome/free-regular-svg-icons';
config.showMissingIcons = false;
library.add(faComments,faCat);
dom.i2svg();
```

↓のように **config.showMissingIcons =false**にすると、アイコンがみつからない場合に MissingIcon(？がアニメするアイコン）を表示しないようなる。

```js:MissingIconを表示しないようにする
config.showMissingIcons = false;
```

これで**npm start**する

```shell
npm start
```

**表示結果**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/614ea3d1-552b-f62f-aa06-9e3e4af24f10.png)
このとおり？マークのアイコンも表示されなくなった。
このように**config**をつかうと挙動を制御することができる。

その他、いくつかの挙動を**Config**で設定することができ[公式](https://fontawesome.com/how-to-use/with-the-api/setup/configuration)に説明がある。

## バンドルをビルドする

ここまではアイコンを個別にインポートするコードを書いて動作を確認してきたが、
Production用のバンドル(app.js)を生成してみる。

```shell:production用ビルドを実行する
npm run build
```

```shell:ビルド結果
Hash: e78c06652d8420836a67
Version: webpack 4.28.4
Time: 548ms
Built at: 2019-01-14 20:56:30
 Asset      Size  Chunks             Chunk Names
app.js  33.7 KiB       0  [emitted]  app
Entrypoint app = app.js
[0] ./src/index.js + 3 modules 818 KiB {0} [built]
    | ./src/index.js 462 bytes [built]
    |     + 3 hidden modules
```

**サイズは33.7KiB**！基本パッケージ版に比べてだいぶ小さくなった。

まとめると以下のとおり。

<table>
<tr><td>ライブラリ</td><td>バンドル対象</td><td>インポート方法</td><td>Webpack4<br>Minimizer</td><td>ビルド時間</td><td>サイズ</td></tr>
<tr><td>基本パッケージ版</td><td>すべてのアイコン</td><td>インポート</td><td>Default(terser)</td><td>1.8s</td><td>679KiB</td></tr>
<tr><td><b>SVGコア版</b></td><td><b>必要なアイコン3個ぶん</b></td><td><b>インポート</b></td><td><b>Default(terser)</b></td><td><b>0.5s</b></td><td><b>33.7KiB</b></td></tr>
</table>

## 本章のソースコード
本章では、**SVGコア**をつかった、最小限のアイコンのインポートをみてきた。
ソースコードは以下のとおり。

https://github.com/riversun/font-awesome5-js-example/tree/master/step02_import


### Font AwesomeのProductionビルドに非常に時間がかかるパターン

あまり出会わないかもしれないが、出会ってしまうとハマるポイントを整理しておく。
それは、Font Awesomeをインポートして、**Production**ビルドをするときに、非常に長い時間待たされるパターンのこと。

そのパターンとは、WebpackするときのMinimizer(JSをminifyしてくれるライブラリ)として独自に<font color=red>**Uglify-JS**</font>を使っているプロジェクト場合は要注意。Ｗebpackとセットで使う場合は**uglifyjs-webpack-plugin**と共に使うことが多いかもしれないが、<font color=red>**Uglify-Js**には **Tree Shaking**（不要なコードを省く処理）に問題</font>があるためビルドに非常に時間がかかる。

では、どうすればいいかというと、基本的には Minimizerを [**terser**](https://github.com/terser-js/terser)に移行すればいい。
[**terser**](https://github.com/terser-js/terser)は、そもそも**Uglify-js**をforkして作られたモノなので機能も近いし、Webpack4はデフォルトのMinimizerとして[**terser**](https://github.com/terser-js/terser)が使われるようになっておりMinimizerを明示的に設定しない状態で、Webpack4をつかって**Production**ビルドする場合は標準では**terser**（※)が利用される。

※**terser**は**terser-webpack-plugin**というパッケージを明示的にインストールして使うことも可能。そのコード例は[こちら](https://github.com/riversun/font-awesome5-js-example/tree/master/step04_with_terser)にのせた


さて、あまりいないかもしれないが、念のためどうしても**Uglify-JS**を使い続けたい場合のための回避策を示す。

まず Uglify-jsベースにするために以下のようにパッケージをインストールして、webpack.config.jsを変更する

#### **Uglify-js**でビルドしてみる

```shell:インストール
npm install uglifyjs-webpack-plugin --save-dev
```

```js:webpack.config.js抜粋
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
...
        optimization: {
            minimizer: [
                new UglifyJSPlugin({
                    uglifyOptions: {compress: {drop_console: true}},
                }),
            ],
        },
```

この状態でProductionビルドすると結果は以下のようになる。

```shell
npm run build
```

```shell
Hash: 5d6d07bebcafd21daab4
Version: webpack 4.28.4
Time: 81642ms
Built at: 2019-01-14 22:56:33
 Asset      Size  Chunks             Chunk Names
app.js  33.3 KiB       0  [emitted]  app
```

なんとUglify-JSベースだと<font color=red>**81秒**</font>もかかってしまう。

<table>
<tr><td>ライブラリ</td><td>バンドル対象</td><td>インポート方法</td><td>Webpack4<br>Minimizer</td><td>ビルド時間</td><td>サイズ</td></tr>
<tr><td>フル版</td><td>すべてのアイコン</td><td>インポート</td><td>Default(terser)</td><td>1.8s</td><td>679KiB</td></tr>
<tr><td rowspan="2">SVGコア版</td><td rowspan="2">必要なアイコン3個ぶん</td><td rowspan="2">インポート</td><td>Default(terser)</td><td>0.5s</td><td>33.7KiB</td></tr>
<tr><td><font color=red><b>Uglify-JS</b></font></td><td><font color=red><b>81.6s</td><td>33.3KiB</td></tr>
</table>

### Deep Import(ディープインポート）

前に書いたとおり**Uglify-JS**では、**Tree Shaking**で不要コードを探索するための処理に問題がある。そこで、その回避策として**Deep Import**（ディープインポート）という方法があるので、以下がそのコード例となる。

```js:index.js（ディープインポートの例)
import { dom, library} from '@fortawesome/fontawesome-svg-core';
import {faDog} from '@fortawesome/free-solid-svg-icons/faDog';
import {faCat} from '@fortawesome/free-solid-svg-icons/faCat';
import {faComments} from '@fortawesome/free-regular-svg-icons/faComments';
library.add(faDog,faComments,faCat);
dom.i2svg();
```

Deep Importは以下のようにダイレクトにアイコン（のパスデータが格納されている）モジュールをインポートする方法となる。
ここでは犬のベクターイメージを格納したモジュールを直接importする例を書いた。

```js
import {faDog} from '@fortawesome/free-solid-svg-icons/faDog';
```

これにより**Uglify-JS**が抱えている**Tree Shaking**問題を回避しビルド（バンドル）時間短縮が期待できる。
実際にビルドしてみると、

```shell
npm run build

Hash: c54bade0ad01d67f30c6
Version: webpack 4.28.4
Time: 625ms
Built at: 2019-01-15 18:52:43
 Asset    Size  Chunks             Chunk Names
app.js  34 KiB       0  [emitted]  app

```

**0.6s**で実行できた！

### 本章のソースコード(deep import)
本章では**Deep Import**をして**Tree Shaking**を回避する方法をみてきた。

以下がそのソースコード

https://github.com/riversun/font-awesome5-js-example/tree/master/step03_import_deeply


## Font Awesomeのバンドル方法のまとめ

これまで**フル版**と**SVGコア版**、それぞれのパッケージでのアイコンのバンドル方法を実際に試しながら見てきた。
アプローチと結果をまとめると以下のようになる。

<table>
<tr><td>ライブラリ</td><td>バンドル対象</td><td>インポート方法</td><td>Webpack4<br>Minimizer</td><td>ビルド時間</td><td>サイズ</td></tr>
<tr><td>フル版</td><td>すべてのアイコン</td><td>インポート</td><td>Default(terser)</td><td>1.8s</td><td>679KiB</td></tr>
<tr><td rowspan="3">SVGコア版</td><td rowspan="3">必要なアイコン3個ぶん</td><td rowspan="2">インポート</td><td>Default(terser)</td><td>0.5s</td><td>33.7KiB</td></tr>
<tr><td>Uglify-JS</td><td>81.6s</td><td>33.3KiB</td></tr>
<tr><td>ディープインポート</td><td>Uglify-JS</td><td>0.6s</td><td>34KiB</td></tr>
</table>

みてわかるとおり、**Font AwesomeのパッケージはSVGコア版-必要最小限のみアイコンをインポート-MinimizerはWebpack4デフォルト(terser)を使う**　というのがいちばん筋が良さそう、ということがわかる。

# まとめ

- Font Awesome5をJSにバンドルする方法について説明しました。
- @fortawesome/fontawesome-svg-core　をつかって個別にアイコンをインポートするとバンドルのサイズを最小限に抑えられることがわかりました
- Minimizerに Uglify-JS を使うとコンパイル時間が長くかかる場合があるため、Webpackを使っている場合は Default(terser)の状態でProductionビルドをするのがオススメです。