iconify を触ってみた (Vite, React, Vue)

[iconify](https://iconify.design/) が良いとの噂を聞き、早速試してみた。

こういうライブラリは本当にありがたいので、作成者さんに感謝なのだが、意外と日本語の知見が少ない印象。
実戦投入が難しい何かしらの理由があると困るので、ハロワと、使い勝手を試してみたので備忘も兼ねて。


# iconify とは

https://iconify.design/

- 膨大なアイコンセットフレームワークを混在させて使える（ [Browse icons](https://icon-sets.iconify.design/) )
- 全体ではなく使うアイコンだけロードする
- 異なるアイコンセットも同じコードで書ける
- 主要なjsフレームワークに最適化されてる
- 自作のアイコンも追加できる
- [Figmaの超便利なプラグイン](https://docs.iconify.design/design/figma/)がある


## なぜiconify？ デザイン戦略としてのアイコンセット問題

「このセットに、あのアイコンが無い。。」
Webデザイナーならほぼ全員がこの問題に頭を抱えた経験があるはず。

フロントエンドなら、その「たった1個の例外のアイコン」をどう実装するか？ と。

これ以上の説明は不要に感じる。
iconifyはそういうソリューションかなと感じる。

## ライセンスは？

コンセプトは理解できるがライセンス心配ですよね。「使えんのそもそも？」と。
[公式サイト](https://iconify.design/)のライセンスはこんな感じ。

```
# License

Iconify is an open source project.
Iconify SVG framework is dual licensed under Apache 2.0 license and GPL 2.0 license. You may select, at your option, one of the above-listed licenses.
Other icon components and tools are licensed under MIT license.
Apache 2.0 and MIT licenses allows pretty much anything, including commercial use.
GPL 2.0 license allows use with more restrictive popular open source projects.
This license does not apply to icons. Icons are released under different licenses, see each icon set for details. Icon sets available by default are all licensed under some kind of open source license.
```



# 実装してみる

今回は [Vite](https://ja.vitejs.dev/) を使って Vanilla,  React と Vue での使用感を試してみた。
ひとまずプレーンな状態を把握したいので、Vanilla環境をインストールして起動確認。

```zsh
% npm init vite@latest
✔ Project name: … vite-project
✔ Select a framework: › vanilla
✔ Select a variant: › vanilla-ts

% cd vite-project
% npm install
% npm run dev
```

## iconifyをインストール

デフォルトっぽい使い方の[こちら](https://docs.iconify.design/icon-components/svg-framework/)でトライ。

```zsh
% npm i -D @iconify/iconify
```

```src/main.ts
import '@iconify/iconify'
```

[こちら](https://icon-sets.iconify.design/flat-color-icons/search/)で使うアイコンを探す。
適当に `search` の検索結果を並べてみる。

![search.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274832/be1a4a3c-ba7f-2acf-e593-4b85de7bafed.png)


こんな感じで使う。

```src/main.ts
import '@iconify/iconify'

const app = document.querySelector<HTMLDivElement>('#app')!

app.innerHTML = `
	<div>
		<span class="iconify" data-icon="akar-icons:search"></span>
		<span class="iconify" data-icon="fa-solid:search"></span>
		<span class="iconify" data-icon="bx:bx-search-alt"></span>
		<span class="iconify" data-icon="bi:search"></span>
		<span class="iconify" data-icon="ant-design:search-outlined"></span>
		<span class="iconify" data-icon="flat-color-icons:search"></span>
	</div>
`
```

![search_view.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274832/2382bda3-f148-dcd6-08b4-7eb1abd07941.png)


デザインの戦略上、こんな使い方をすることは決して無いだろうけど。
全然違うアイコンセットから、簡単に取り出して、混ぜて使える。驚くほど簡単。


# React で iconify を試す

ささっとViteでReact環境をつくる。

```
% npm init vite@latest
✔ Project name: … vita-react
✔ Select a framework: › react
✔ Select a variant: › react-ts

% cd vite-react
% npm install
% npm run dev
```
 
[react用のパッケージ](https://docs.iconify.design/icon-components/react/)を入れる。
 
```zsh
% npm install --save-dev @iconify/react
```

Font Awesome から 10個のアイコンを並べてみた結果。
驚くべき簡単さ。

```src/App.tsx
import { Icon } from '@iconify/react';

function App() {
  return (
    <div className="App">
      <Icon icon="fa-solid:archive" />
      <Icon icon="fa-solid:book" />
      <Icon icon="fa-solid:coffee" />
      <Icon icon="fa-solid:drum" />
      <Icon icon="fa-solid:envelope" />
      <Icon icon="fa-solid:fire" />
      <Icon icon="fa-solid:gift" />
      <Icon icon="fa-solid:history" />
      <Icon icon="fa-solid:info" />
      <Icon icon="fa-solid:key" />
    </div>
  )
}

export default App
```


![icons.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274832/b6ee98eb-823b-9457-8895-397aab7c1dac.png)



## 比較用に Font Awesome

よく使われるアイコンフォントフレームワークの [Font Awesome](https://fontawesome.com/v5.15/how-to-use/on-the-web/using-with/react) をこのreactに追加して比較してみる。

アイコンは、上記の例と同じ10個を並べる。

```zsh
% npm i --save @fortawesome/fontawesome-svg-core
% npm install --save @fortawesome/free-solid-svg-icons
% npm install --save @fortawesome/react-fontawesome
```

```src/App.tsx

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faArchive, faBook, faCoffee, faDrum, faEnvelope, faFire, faGift, faHistory, faInfo, faKey } from '@fortawesome/free-solid-svg-icons'

function App() {
  return (
    <div className="App">
      <FontAwesomeIcon icon={faArchive} />
      <FontAwesomeIcon icon={faBook} />
      <FontAwesomeIcon icon={faCoffee} />
      <FontAwesomeIcon icon={faDrum} />
      <FontAwesomeIcon icon={faEnvelope} />
      <FontAwesomeIcon icon={faFire} />
      <FontAwesomeIcon icon={faGift} />
      <FontAwesomeIcon icon={faHistory} />
      <FontAwesomeIcon icon={faInfo} />
      <FontAwesomeIcon icon={faKey} />
    </div>
  )
}

export default App

```

工夫次第ではありそうだが、使いたいアイコンセットや個別のアイコンをそれぞれimportして使うイメージ。

## buildを比較

`npm run build` でbuild結果を見比べてみる。
正直サイズが小さすぎてよくわからないが、肥大化していまっている、みたいな事は無いと考えてよいのか。

### iconifyのみのbuild

```
vite v2.7.13 building for production...
✓ 32 modules transformed.
dist/assets/favicon.17e50649.svg   1.49 KiB
dist/index.html                    0.52 KiB
dist/assets/index.7e2ffea8.js      1.22 KiB / gzip: 0.60 KiB
dist/assets/index.458f9883.css     0.29 KiB / gzip: 0.22 KiB
dist/assets/vendor.f5504cc1.js     154.40 KiB / gzip: 50.17 KiB
```

### fontawesomeのbuild

```
vite v2.7.13 building for production...
✓ 40 modules transformed.
dist/assets/favicon.17e50649.svg   1.49 KiB
dist/index.html                    0.52 KiB
dist/assets/index.d3bc5bb0.js      1.13 KiB / gzip: 0.60 KiB
dist/assets/index.458f9883.css     0.29 KiB / gzip: 0.22 KiB
dist/assets/vendor.c0578e15.js     163.71 KiB / gzip: 53.92 KiB
```


# Vue3 で iconify を試す

同じ事を、Vueで試してみる。 
ViteでVue環境をつくる。

```zsh
% npm init vite@latest
✔ Project name: … vite-vue
✔ Select a framework: › vue
✔ Select a variant: › vue-ts

% cd vite-vue
% npm install
% npm run dev
```

iconifyを入れる。[vue3](https://docs.iconify.design/icon-components/vue/) と [vue2](https://docs.iconify.design/icon-components/vue2/) で方法が別れている。
今回は Vue3で。


```zsh
% npm install --save-dev @iconify/vue
```

こんな感じ。やっぱり驚くほど簡単。

```src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { Icon } from '@iconify/vue'

createApp(App)
  .component('Icon', Icon )
  .mount('#app')
```

```src/App.vue
<script setup lang="ts"></script>

<template>
  <div>
    <Icon icon="fa-solid:archive" />
    <Icon icon="fa-solid:book" />
    <Icon icon="fa-solid:coffee" />
    <Icon icon="fa-solid:drum" />
    <Icon icon="fa-solid:envelope" />
    <Icon icon="fa-solid:fire" />
    <Icon icon="fa-solid:gift" />
    <Icon icon="fa-solid:history" />
    <Icon icon="fa-solid:info" />
    <Icon icon="fa-solid:key" />
  </div>
</template>

<style></style>
```

## 比較用に Font Awesome

Vue用には [公式のVue.jsコンポーネント](https://www.npmjs.com/package/@fortawesome/vue-fontawesome)がある。

```zsh
% npm install --save @fortawesome/fontawesome-svg-core
% npm install --save @fortawesome/free-solid-svg-icons
% npm i --save @fortawesome/vue-fontawesome@prerelease
```

```src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faArchive, faBook, faCoffee, faDrum, faEnvelope, faFire, faGift, faHistory, faInfo, faKey } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'

library.add(faArchive, faBook, faCoffee, faDrum, faEnvelope, faFire, faGift, faHistory, faInfo, faKey)

createApp(App)
  .component('fa', FontAwesomeIcon )
  .mount('#app')
```

```src/App.vue
<script setup lang="ts"></script>

<template>
  <div>   
    <fa icon="archive" />
    <fa icon="book" />
    <fa icon="coffee" />
    <fa icon="drum" />
    <fa icon="envelope" />
    <fa icon="fire" />
    <fa icon="gift" />
    <fa icon="history" />
    <fa icon="info" />
    <fa icon="key" />
  </div>
</template>

<style></style>

```


## buildを比較

やはり、大丈夫そうかな？くらいの感想しか言えない結果だが。一応。

iconifyのみのbuild

```
vite v2.7.13 building for production...
✓ 11 modules transformed.
dist/index.html                  0.42 KiB
dist/assets/index.992dd85d.js    1.27 KiB / gzip: 0.63 KiB
dist/assets/vendor.11823ad8.js   71.00 KiB / gzip: 27.09 KiB
```

fontawesomeのbuild

```
vite v2.7.13 building for production...
✓ 13 modules transformed.
dist/index.html                  0.42 KiB
dist/assets/index.4b3fc9b6.js    1.27 KiB / gzip: 0.67 KiB
dist/assets/vendor.5198193f.js   83.21 KiB / gzip: 31.14 KiB
```


# ざっくりまとめ

ここまでの結果を踏まえての印象は、とにかく簡単で、フットワークが軽いという印象。
Font Awesome の例でも、正直公式よりも楽だ。

これを触ってしまうと、もう二度とsvgスプライトとか開発したくないなあと感じる。

実戦では [Iconify Tools](https://docs.iconify.design/tools/tools2/) を使ってもう少し突っ込んだ開発になりそうなので、もう少し使い込んでみたい。