SketchできれいなSVGファイルを出力する方法

## 概要
Sketchを使えば手軽にSVG形式のアイコンやグラフィックを書き出せますが、書き出したデータをよく見てみると、データが想像以上に重かったり、不要なタグが付いていたりとムラが発生する時があります。
この記事では**Sketchからなるべく無駄のない、きれいなSVGを出力する手法を紹介します。**

![icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22445/6652ee5e-ce1b-4158-b145-2048c716071e.png)
<small>今回の検証で使うサンプルアイコン</small>

## エクスポート前にやること

### アートボードそのものを書き出し対象とする
アートボードでなく、アイコンをグループ化してグループのみを書き出すと、一見普通に書き出せますが、`viewBox`の値が書き出したアイコンの図形のサイズで設定されるため、各アイコンのサイズがバラバラになってしまうためです。

### レイヤー名は必ず英語表記にする
レイヤーが日本語のままだと、`id`などに日本語がそのまま入ってしまうので、レイヤー名は必ず英語にして出力します。

### 図形はすべてCombineしてパス化する

Combineしたファイルは図形をパス情報化するため、データサイズが膨らみますが、`path`ひとつとなるため、管理がしやすくなります。サイズ最小化にこだわったり、個別に色を変えたり動かしたりしない限り、パスを正しくまとめることで余計なタグがない綺麗なsvgが出力できます。  

```xml:パス化前
<?xml version="1.0" encoding="UTF-8"?>
<svg width="128px" height="128px" viewBox="0 0 128 128" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
    <title>NotGroup</title>
    <desc>Created with Sketch.</desc>
    <g id="NotGroup" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <circle id="Oval" fill="#000000" cx="28" cy="34" r="10"></circle>
        <rect id="Rectangle" fill="#000000" x="50" y="27" width="59" height="14"></rect>
        <circle id="Oval" fill="#000000" cx="28" cy="66" r="10"></circle>
        <rect id="Rectangle" fill="#000000" x="50" y="59" width="59" height="14"></rect>
        <circle id="Oval" fill="#000000" cx="28" cy="98" r="10"></circle>
        <rect id="Rectangle" fill="#000000" x="50" y="91" width="59" height="14"></rect>
    </g>
</svg>
```

```xml:パス化後
<?xml version="1.0" encoding="UTF-8"?>
<svg width="128px" height="128px" viewBox="0 0 128 128" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
    <title>Combined</title>
    <desc>Created with Sketch.</desc>
    <g id="Combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <path d="M28,44 C22.4771525,44 18,39.5228475 18,34 C18,28.4771525 22.4771525,24 28,24 C33.5228475,24 38,28.4771525 38,34 C38,39.5228475 33.5228475,44 28,44 Z M50,27 L109,27 L109,41 L50,41 L50,27 Z M28,76 C22.4771525,76 18,71.5228475 18,66 C18,60.4771525 22.4771525,56 28,56 C33.5228475,56 38,60.4771525 38,66 C38,71.5228475 33.5228475,76 28,76 Z M50,59 L109,59 L109,73 L50,73 L50,59 Z M28,108 C22.4771525,108 18,103.522847 18,98 C18,92.4771525 22.4771525,88 28,88 C33.5228475,88 38,92.4771525 38,98 C38,103.522847 33.5228475,108 28,108 Z M50,91 L109,91 L109,105 L50,105 L50,91 Z" id="Combined-Shape" fill="#000000"></path>
    </g>
</svg>
```

## SVGの圧縮

特段何も設定しなくてもSVGとしてエクスポートできますが、必要でないタグが多数含まれています。
``<?xml version="1.0">``や``<title>``、``<desc>``といったmeta情報は、SVGファイルの必須タグではないので削除できます。SVGはxmlなので、VScodeなどエディタで開いて除去することも可能ですが、マニュアルでやるのは非常にめんどくさいです。そのため、Webサービス、一括書き換えツールなどを使い、SVGの圧縮を行います。


### Sketchのプラグインを使って圧縮

Sketchのプラグインを使ってエクスポート時に最適化する方法です。使い方は簡単で[BohemianCoding/svgo-compressor](https://github.com/BohemianCoding/svgo-compressor)をインストールするだけで、SVG書き出し時に圧縮最適化して書き出してくれます。出力結果は以下の通りです。

```xml:SVGO.svg
<svg xmlns=“http://www.w3.org/2000/svg” width=“128” height=“128” viewBox=“0 0 128 128”>
  <path fill-rule=“evenodd” d=“M28,44 C22.4771525,44 18,39.5228475 18,34 C18,28.4771525 22.4771525,24 28,24 C33.5228475,24 38,28.4771525 38,34 C38,39.5228475 33.5228475,44 28,44 Z M50,27 L109,27 L109,41 L50,41 L50,27 Z M28,76 C22.4771525,76 18,71.5228475 18,66 C18,60.4771525 22.4771525,56 28,56 C33.5228475,56 38,60.4771525 38,66 C38,71.5228475 33.5228475,76 28,76 Z M50,59 L109,59 L109,73 L50,73 L50,59 Z M28,108 C22.4771525,108 18,103.522847 18,98 C18,92.4771525 22.4771525,88 28,88 C33.5228475,88 38,92.4771525 38,98 C38,103.522847 33.5228475,108 28,108 Z M50,91 L109,91 L109,105 L50,105 L50,91 Z”/>
</svg>
```

なお、このプラグインは、[svgo](https://github.com/svg/svgo)というNode.jsベースのOptimizerを使っているので、これ単体をWebpackやGulpに組み込むことで、ビルド時などに一括して圧縮、といった方法も考えられます。

### Webサービスを使って圧縮
[SVGOMG - SVGO’s Missing GUI](https://jakearchibald.github.io/svgomg/)というWebサービスを使います。使い方は簡単で、サービスから圧縮したいSVGをアップロード、値を調整して書き出すと、最適化された形で出力されます。他サービスと比較検証しましたが、書き出しサイズ的に一番軽量になりました。

```xml:svgomg.svg
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M28 44c-5.523 0-10-4.477-10-10s4.477-10 10-10 10 4.477 10 10-4.477 10-10 10zm22-17h59v14H50V27zM28 76c-5.523 0-10-4.477-10-10s4.477-10 10-10 10 4.477 10 10-4.477 10-10 10zm22-17h59v14H50V59zm-22 49c-5.523 0-10-4.477-10-10s4.477-10 10-10 10 4.477 10 10-4.477 10-10 10zm22-17h59v14H50V91z" fill="#000" fill-rule="evenodd"/></svg>
```

#### 他Webサービス
* [SVG Minifier](https://www.svgminify.com/)
* [SVG-Optimiser](https://petercollingridge.appspot.com/svg-optimiser)


## まとめ
SketchできれいなSVGを出力するためのコツは、以下のとおりです。

1. **パスはまとめて一個の複合パスにまとめる**
2. **レイヤー名は必ず英語表記にする**
3. **書き出し時はアートボード単位で書き出す**
4. **Sketchからの書き出しはsvgo-compressorを使うと、綺麗に圧縮できる**
5. **Webツールで軽量化するならSVGOMGが軽量で良い**

---
最近はデザインに多くリソースを割いており、そんな中で気になった小ネタでした。現場からは以上です。