---
# System prepended metadata

title: '[IM008] Storage'
tags: [HTML, ironman]

---

# [IM008] Storage

> **前言**
> 2020 秋天，我將用 30 天的時間，來嘗試回答和網路前端開發相關的 30 個問題。30 天無法一網打盡浩瀚的前端知識，有些問題可能對有些讀者來說相對簡單，不過期待這趟旅程，能幫助自己、也幫助讀者打開不同的知識大門。有興趣的話，跟著我一起探索吧！
>
![Imgur](https://i.imgur.com/Ovvk4hF.png)

## Storages in browswer

瀏覽器本身是一個功能非常強大的應用程式，除了可以解析 HTML, CSS, JavaScript 文件，渲染出使用者看得到的畫面，也有提供各種不同的儲存空間，來提供開發者或使用者使用。

以上圖的 Chrome 來說，就有
* Local Storage
* Session Storage
* IndexedDB
* Web SQL
* Cookies

如果打開 Safari

![Imgur](https://i.imgur.com/Iq3h1pI.png)

也可以看到類似的儲存方式。今天就讓我們來花一點時間來看看這些不同的儲存方式吧！

## Cookie

首先先來看看大家非常熟悉的 Cookie。由於 HTTP 是無狀態的協議，所以 server 其實不知道使用者上一次做了什麼請求，所以也就不知道該如何在這次的請求當中，做出更合適的回應。

當然，如果這個網站只是單方面的讓使用者讀取資訊，那也就沒有什麼太的問題，就像是圖書館裡面的書本，不需要知道讀者在上一秒看過了什麼東西。但如果這個網站是一個需要與使用者高度互動的應用程式，那麼就需要有個方法，知道使用者上一步做了什麼事情。

因此在 1994 年左右，Netscape 的工程師 Lou Montulli 有個大膽的想法，將 UNIX programming 當中的 "magic cookie"，應用在瀏覽器上面。"magic cookie" 是一個 token 或是簡短的資訊，作為程式彼此溝通時使用。

在無狀態的 HTTP 協議當中，如果 server 和使用者在溝通的過程中，能夠順手帶上 cookie 送給對方，就可以記錄使用者的狀態，甚至可以追蹤使用者的動態。

那麼，cookie 是放在哪裡呢？當 server 要回傳 response 的時候，可以在 response header 用 Set-Cookie 放入想要送出的 cookies。

```
Set-Cookie: <cookie-name>=<cookie-value>
```

當中，cookie 本身的結構是 key-value pair，也就是有一個 `name` 和 `value` 的組合。舉例如下：

```
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
```

除了基本的 key-value 之外，還可以放入其他屬性，像是
* Domain
* Path
* Expires
* SameSite
* HttpOnly

等等。

當這些資訊被送到瀏覽器的時候，就會被瀏覽器給儲存起來。如果在iT邦幫忙鐵人賽網頁當中打開 DevTool，就會看到下面這麼多個 cookies

![Imgur](https://i.imgur.com/hHQzCPY.png)


這樣看起來，好像有了 cookie 就可以解決所有問題了！不過其實還是有一些限制：
* 目前大多數瀏覽器限制 cookie 的大小為 4096 bytes，如果有更多的資訊需要儲存，那麼 cookie 就不太夠用
* 瀏覽器僅支援 50 個來自單一 domain 的 cookies
* 有些使用者會禁止瀏覽器使用 cookie，所以 server 就無從得知使用者的狀態
* Cookie 有被竄改的風險，造成安全性的問題

## Local storage & Session storage

HTML5 的出現，帶來了許多更先進、方便的 API，其中一個就是 web storage。

Web storage，也有人稱做 DOM storage，提供了應用程式在瀏覽器端儲存使用者資料的功能，當中包含了 local storage 和 session storge 兩種方法。

local storage 和 session storage 儲存和操作資料的方法很像，最大的差異在於 local storage 可以持續保留在瀏覽器當中，並且可以跨 tabs （不同分頁）存取；而 session storage 則無法跨 tabs 存取，且會在該頁面 session 結束的時候被清除。

要儲存資料到 web storage 當中，以 local storage 為例，同樣是以 key-value pair 的方式存放資料，而 key-value 都會被轉為字串存入。方法如下：
```htmlmixed=
localStorage.setItem('name', 'td')
localStorage.age = 18
```
取得資料
```javascript=
localStorage.getItem('name', 'td')   // 'td'
localStorage.age                     // '18'
```
清除資料
```javascript=
localStorage.removeItem('name')
localStorage.clear()
```

Web storage 的儲存空間就比 cookie 大許多，其大小根據不同瀏覽器支援的程度有所差異，不過至少都有 5MB 以上的儲存空間。

## IndexedDB

雖然 Web storage 已經提供了一個相當不錯的儲存方式，不過跟一般資料庫比起來，少了很重要的搜尋功能，而且儲存空間還是有限（其實不管有多少都不夠），因此有人提出了 IndexedDB 的方案，希望能夠更提升瀏覽器的儲存功能。

IndexedDB，也稱作 Indexed Database API，是一種類似 NoSQL 的儲存方式，提供 key-value pair 的儲存方式，同時支援搜尋、transaction 等功能，和 localStorage 不同的是，IndexedDB 是非同步的操作，因此可以讀寫大筆資訊，而不會影響到瀏覽器的運作。

如果想要嘗試操作，可參考 [MDN 的介紹](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB) 或 [第一次使用 IndexedDB 存取資料就上手](https://tech.mozilla.com.tw/?p=631) 這篇文章。

## Web SQL

最後要提到的儲存方式是 Web SQL，和 IndexedDB 要處理的問題一樣，差異在 Web SQL 支援 SQL 語法的查詢。不過在 2010 年 [W3C 的文件](https://www.w3.org/TR/2010/NOTE-webdatabase-20101118/) 上，已經停止繼續維護 Web SQL 的規格了。雖然在 Chrome 上面可能還可以操作，不過基本上短期不會變成標準規格或普及化的情況發生。


## Ending

無意間打開 Chrome DevTool 發現有許多不同的儲存方式，不過目前比較實用的就是 web storage。IndexedDB 也許還可以嘗試，不過我想 Web SQL 就可以先暫時跳過。

之後有機會，再來多聊聊瀏覽器相關的事物吧！

### Ref
* [HTTP cookies (MDN)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)
* [Magic cookie](https://en.wikipedia.org/wiki/Magic_cookie)
* [THE PAST, PRESENT & FUTURE OF LOCAL STORAGE FOR WEB APPLICATIONS](https://diveintohtml5.info/storage.html)
* [Web storage](https://en.wikipedia.org/wiki/Web_storage)


***
> **TD**
> Be curious as astronomer, think as physicist, hack as engineer, 
fight as baseball player
> [More about me](https://tsungtingdu.github.io/profile/)
> 
> *"Life is like riding a bicycle. To keep your balance, you must keep moving."*

***

###### tags: `ironman` `HTML`