Base64エンコーディング徹底解説：基本から応用まで

[![Group55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/cb42a553-7eea-4462-a61a-990c19f77c55.png)](https://leapcell.io/?lc_t=q_base64)


**[Leapcell：次世代のサーバレスWebホスティングプラットフォーム](https://leapcell.io/?lc_t=q_base64)**

# Base64の深層理解：原理、応用、およびフロントエンドの実践

フロントエンド開発において、プロジェクトの最適化はパフォーマンス向上の重要な側面です。一般的な最適化戦略の1つは、小さな画像を適切にBase64文字列に置き換えることで、ページ上のHTTPリクエスト数を減らすことです。同時に、これらは通常、特定のキロバイト数を超えない小さな画像であることが強調されています。では、Base64とはいったい何でしょうか？ また、なぜフロントエンドの最適化に役立つのでしょうか？ 一緒に深く掘り下げて調べてみましょう。

## 最初の理解
次のような文字列にはおなじみかもしれません。
```
data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0c......
```
この固定形式を通じて、画像を表すことができ、ブラウザはそれを認識し、対応する画像を完全に表示することができます。上記の例はSVG形式の画像を示しています。実際、ブラウザがサポートする任意の形式の画像を読み込むこともできます。この文字列はBase64エンコードに基づいて生成され、`base64,`の後の長い文字列がBase64エンコードされた文字列です。

## Base64の誕生
インターネットの開発初期、電子メールは最も有効なアプリケーションの1つでした。しかし、当初は電子メールのSMTP送信プロトコルは7ビットのASCIIコードのみを送信するために使用できました。ASCIIコードは英語に基づいて設計されていたため、このプロトコルを通じて英語以外の国のテキストなどのリソースを送信できない状況が生じました。この問題を解決するため、後にMultipurpose Internet Mail Extensions（MIME）が登場しました。MIMEは電子メールの主要な構造を追加し、非ASCIIコードのエンコードと送信規則を定義しました。これがBase64の起源です。文字エンコードの知識を深く理解したい場合は、フロントエンド開発で理解する必要がある文字エンコードの知識を参照してください。

## 基本定義
Base64は、64の印刷可能な文字に基づいてバイナリデータを表すエンコードおよびデコード方法です。そのエンコードとデコードの特性から、その主な機能はセキュリティではなく、様々なゲートウェイ間でエラーなくコンテンツを送信できるようにすることです。これら64の印刷可能な文字には、26の大文字A - Z、26の小文字a - z、10の数字0 - 9の合計62文字、それに2つの他の文字`+`と`/`が含まれます。Base64はインデックスベースのエンコードであり、各文字は1つのインデックスに対応しています。具体的な関係図は以下の通りです。


[![1461.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/aa5d9157-2707-49da-a0ec-7d501b9c167b.png)](https://leapcell.io/?lc_t=q_base64)


これが名前の中の「64」の由来でもあります。

## エンコード方法
64は2の6乗に等しいため、Base64の1文字は実際には6ビット（bit）のバイナリデータを表します。ただし、バイナリデータでは1バイトが8ビット（bit）に対応します。したがって、3バイト（3 x 8 = 24ビット）の文字列またはバイナリデータは、正確に4つのBase64文字（4 x 6 = 24ビット）に変換できます。なぜ3バイト単位でグループ化するのでしょうか？ 6と8の最小公倍数は24であり、24ビットはちょうど3バイトだからです。具体的なエンコード方法は以下の通りです。
1. 3バイトごとに1グループにする。3バイトは合計24ビットのバイナリデータを持つ。
2. これら24ビットのバイナリデータを4つのグループに分割し、各グループを6ビットにする。
3. 6ビットの各グループの前に2つの00を追加し、32ビットに拡張する、つまり4バイトにする。
4. 各バイトは64未満の数に対応し、これが文字番号である。
5. そして、文字インデックス関係表に従って、各文字番号は1文字に対応し、Base64エンコードされた文字が得られる。


[![base64-Two.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/dba8a8ad-9226-43a9-8a4e-43a0dad0a8d2.png)](https://leapcell.io/?lc_t=q_base64)


例えば、上記の図の`two`という文字列は、対応するエンコードに変換されます。

## 容量増加
3文字がBase64変換によってエンコードされると、最終的に4文字になります。これは、各6ビットの位置に2つの0がパディングされて8ビットの位置になり、1バイトに対応するためです。ここではちょうど3分の1多くなります。したがって、通常の状況では、Base64エンコードされたデータの容量は通常、元のデータよりも3分の1大きくなります。これが、先ほど述べたBase64エンコードを使用して画像を最適化する際に、小さなアイコンであることを強調する必要がある理由です。すべての画像をこの方法で処理すると、静的ファイルが大幅に増加し、好ましくありません。

## 「=」記号
3つの英字は正確に4つのBase64文字に変換できます。文字長が3の倍数でない場合はどうでしょうか？ どのような規則に従う必要がありますか？ 実際のBaseエンコードの使用では、65番目の文字、つまり`=`記号の存在に気づくことがよくあります。この等号は、この特殊な状況の処理方法です。3バイト未満の部分には、実際には24ビットになるまで末尾に0が追加されます。ただし、バイト数を計算する際には、総長を直接3で割ることに注意する必要があります。余りが1の場合は、末尾に直接`=`を追加します。余りが2の場合は、`=`を2つ追加します。したがって、トランスコードされた文字列に追加する必要があるサフィックスの等号は1つまたは2つです。具体的な状況は以下の図を参照してください。


[![base64-remaining-2-characters.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/56f28a07-a19e-4111-bfea-09306df33f7c.png)](https://leapcell.io/?lc_t=q_base64)


図の2番目のケースでは、単一の文字`d`はインデックス文字表のインデックス0を区別するために使用されます。このとき、得られるエンコードでは、インデックス0に対応する`A`文字があり、直接`=`を2つ追加します。

## 非ASCII文字
Base64はASCII文字のみをエンコードできるため、日本語の文字などの非ASCII文字の場合、まず日本語の文字をASCII文字に変換してからエンコードする必要があります。

## エンコードとデコード方法
### btoaとatob
JavaScriptはBase64エンコードを処理するための2つのネイティブメソッド`btoa()`と`atob()`を提供しています。
- `btoa()`: 文字列またはバイナリ値をBase64エンコードされた文字列に変換します。`btoa`メソッドはASCIIコードの文字のみを直接処理できることに注意する必要があります。非ASCIIコードの文字の場合はエラーが発生します。
- `atob()`: Base64エンコードされた文字列のデコードを行います。`atob`メソッドに渡される文字列パラメータが有効なBase64エンコードでない場合（例えば非ASCII文字）、またはその長さが4の倍数でない場合は、エラーが発生します。

```javascript
btoa('you') // 'eW91'
atob('eW91') // 'you'
btoa('馬鹿') // Uncaught DOMException: The string to be encoded contains characters outside of the Latin1 range.
atob('y') // Uncaught DOMException: The string to be decoded is not correctly encoded.
```
### 日本語の文字の処理
`btoa`と`atob`はASCII文字、つまり1バイト文字のエンコードのみをサポートしており、通常出会う日本語の文字は2 - 4バイト文字です。したがって、日本語の文字はまずUTF - 8エンコードに変換し、UTF - 8エンコードを1文字と見なすことで、複数の1バイト文字をエンコードすることができます。日本語には`encodeURIComponent()`と`decodeURIComponent()`の2つのメソッドを使用できます。
- `encodeURIComponent()`: 非ACSII文字をUTF - 8にエンコードします。
- `decodeURIComponent()`: デコードに使用されます。

以下は日本語のエンコードとデコードの方法です。
```javascript
window.btoa(encodeURIComponent('馬鹿'))
// 'JUU5JUE2JUFDJUU5JUI5JUJG'
decodeURIComponent(window.atob('JUU5JUE2JUFDJUU5JUI5JUJG'))
// '馬鹿'
```
### サードパーティライブラリ
例えば、`js - base64`です。フロントエンド開発では、このようなサードパーティライブラリを使用して、Base64関連の操作をより便利に処理することもできます。

## 一般的なフロントエンドの応用
次に、フロントエンド開発におけるBase64エンコードの一般的な使用シナリオを見てみましょう。フロントエンドにおけるBase64の応用の多くは画像処理に関するもので、一般的にDataURLメソッドに基づいています。Data URLは4つの部分で構成されています：`data:`プレフィックス、MIMEタイプ（データの種類を示す）、`base64`フラグ（テキストの場合は省略可能）、そしてデータ自体です。具体的な形式は：`data:[<mime type>][;base64],<data>`です。ここで4番目の部分`<data>`、つまりデータ自体はBase64文字列です。
### 小さな画像のトランスコード
つまり、最初に述べた画像最適化のためにBase64を使用してリクエスト数を減らすシナリオです。`img`タグの下で使用することも、`css`内で使用することもできます。
```html
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0c......Ii8+PC9nPjwvc3ZnPg==">
```
```css
.icon {
  background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0c......Ii8+PC9nPjwvc3ZnPg==);
}
```
VueやReactフレームワークを使用する場合、`url - loader`を通じて設定を行い、Base64に変換するアイコンのサイズを設定することもできます。
```javascript
.loader('url - loader')
.tap(options => {
  options.limit = 10240 // 10kb
  return options
})
```
### ファイル読み取り
Web環境では、`FileReader` APIが提供され、ファイルのデータを読み取ることができます。その`readAsDataURL()`メソッドを使用して、ファイルデータをBase64エンコードされた文字列データとして読み取ることができます。
```javascript
let reader = new FileReader()
reader.onload = () => {
  let base64Img = reader.result
};
reader.readAsDataURL(file)
```
この方法は画像アップロードでよく使用されます。

### Canvasによる画像生成
Canvasは基本的にビットマップ画像です。`toDataURL()`メソッドを提供し、Canvasを画像としてエクスポートすることができ、この画像はBase64エンコード形式で保存されます

```javascript
const dataUrl = canvasEl.toDataURL()
// data:image/png;base64,PHN2ZyB4bWxucz0iaHR0c......
```
### その他
画像表示の処理以外にも、Base64エンコードされた文字列は、特殊なデータ伝送、単純なエンコードと暗号化、コードの難読化、そして一部の証明書にも見られます。

## まとめ
最後に、Base64の特徴をまとめましょう：
 - バイナリデータを文字列（ASCIIコード）に変換し、データ伝送を容易にします。
 - ブラウザはBase64エンコードされた画像を直接表示でき、リクエストを減らします。
 - エンコードされたデータは少なくとも3分の1大きくなり、エンコードとデコードの処理には追加の方法が必要です。

Base64を深く理解することで、フロントエンド開発においてより合理的に使用することができ、パフォーマンスを最適化しながら、様々なデータ伝送と表示の要件をより良く処理することができます。 

# [Leapcell：次世代のサーバレスWebホスティングプラットフォーム](https://leapcell.io/?lc_t=q_base64)


[![barndpic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/467f0469-cf4b-4178-8789-cb947e4bf2e3.png)](https://leapcell.io/?lc_t=q_base64)


最後に、Webサービスのデプロイに最適なプラットフォーム **[Leapcell](https://leapcell.io/)** をおすすめします。

### 1. 多言語対応  
 - JavaScript、Python、Go、またはRustで開発できます。  

### 2. 無制限のプロジェクトを無料でデプロイ  
 - 使用量に応じて課金 — リクエストがなければ料金はかかりません。

### 3. 圧倒的なコスト効率  
 - 使い放題で、アイドル時の料金はかかりません。  
 - 例：25ドルで平均応答時間60msで694万回のリクエストに対応可能。  

### 4. ストリームライン化された開発者体験  
 - 直感的なUIで簡単にセットアップ可能。  
 - 完全自動化されたCI/CDパイプラインとGitOps統合。  
 - アクション可能な洞察のためのリアルタイムメトリックとロギング。  

### 5. 簡単なスケーラビリティと高パフォーマンス  
 - 高い同時接続数を簡単に処理するための自動スケーリング。  
 - 運用オーバーヘッドはゼロ — 開発に集中できます。  


[![Frame3-withpadding2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/05000be8-60df-4e63-a62f-06d0e36b4233.png)](https://leapcell.io/?lc_t=q_base64)


[ドキュメントで詳細をご覧ください！](https://docs.leapcell.io/)

LeapcellのTwitter：[https://x.com/LeapcellHQ](https://x.com/LeapcellHQ)