Como utilizar e quais as diferenças entre sessionStorage e localStorage

O localStorage e sessionStorage são recursos importantes da API de Armazenamento da Web (Web Storage API), que permitem aos desenvolvedores armazenar dados localmente no navegador do usuário. Neste texto, vamos explorar como estes recursos funcionam dando enfâse nas diferenças.

localStorage e sessionStorage

Ambos os recursos permitem armazenar dados no navegador do usuário em pares chave/valor, ambos em formato string. Os dados armazenados podem ser recuperados e usados posteriormente em seu site ou aplicativo da web.

Exemplo de dados salvos no sessionStorage

Ao contrário dos cookies, que também armazenam informações no navegador do usuário e podem ser acessados e manipulados pelo servidor e navegador, os dados do armazenados no localStorage e sessionStorage só podem ser acessados pelo navegador (client-side). Além disto, o limite de armazenamento é bem maior que os cookies, podendo variar entre os navegadores.

Cookies are restricted to 4 kilobytes. Web storage provides far greater storage capacity:

Opera 10.50+ allows 5 MB
Safari 8 allows 5 MB
Firefox 34 allows 10 MB[5] (formerly 5 MB per origin in 2007)
Google Chrome allows 10 MB per origin (formerly 5 MB per origin)
Internet Explorer allows 10 MB per storage area

https://en.wikipedia.org/wiki/Web_storage

Uma outra característica importante é que os navegadores separam os dados armazenados no localStorage e sessionStorage de acordo com a origem. A origem é definida pelo protocolo, domínio e porta. Cada origem tem sua própria área isolada de outras, deixando os dados completamente separados e inacessíveis à outras origens. Por exemplo, se um script em uma página acessa o localstorage usando a chave "minhaChave" em http://teste.com.br, outro script em uma página diferente que também esteja em http://teste.com.br terá acesso a essa chave. Mas se uma das páginas estiver usando https ou uma porta diferente, o navegador considerará as duas páginas como de origens diferentes e não permitirá o acesso ao localStorage entre elas.

Representação do isolamento do localStorage e sessionStorage para diferentes origens

Observação: quando não especificamos a porta no protocolo http, o default é 80, já no https é a 443.

localStorage

O localStorage tem as seguintes características com relação aos dados armazenados:

  • não tem um tempo de expiração no navegador. Então os dados permanecem disponíveis mesmo após o usuário fechar e reabrir o navegador.
  • são compartilhados com abas/janelas que estão acessando a mesma origem.

Exemplo de uso:

// salva um novo valor
localStorage.setItem('username', 'consolelog');

// consulta um valor através da chave
const username = localStorage.getItem('username');
console.log(username); // Output: "consolelog"

// remove 
localStorage.removeItem('username');

sessionStorage

Já no sessionStorage podemos citar as seguintes características:

  • os dados são armazenados de modo temporário. Então os dados são apagados automaticamente quando o usuário fecha o navegador (ou aba/janela).
  • os dados não são compartilhados entre abas ou janelas, mesmo quando estão acessando a mesma origem.

Exemplo de uso:

// salva um novo valor
sessionStorage.setItem('username', 'consolelog');

// consulta um valor através da chave
const username = sessionStorage.getItem('username');
console.log(username); // Output: "consolelog"

// remove 
sessionStorage.removeItem('username');

Exemplo 1 - como utilizar o localStorage e sessionStorage

Como primeiro exemplo vamos tomar um cenário bem simples, salvar uma informação no localStorage e sessionStorage e consultá-la via script e também via ferramenta do desenvolvedor (DevTools).

O script para realizar este trabalho é bem simples:

// salva um novo valor
localStorage.setItem('username', 'consolelog1');

// consulta um valor através da chave
console.log(localStorage.getItem('username')); // Output: "consolelog1"

// ***

// salva um novo valor
sessionStorage.setItem('username', 'consolelog2');

// consulta um valor através da chave
console.log(sessionStorage.getItem('username')); // Output: "consolelog2"

Para abrir as ferramentas do desenvolvedor no Chrome utilize o atalho command + option + J no MacOS ou ctrl + shift + J no Windows:


Executando o script no navegador

Após executar o script é possível consultar os valores salvos na aba "Application":

Consultando os valores do sessionStorage
Consultando os valores do localStorage

Exemplo 2 - como funciona com <iframe>?

Em um outro cenário, razoavelmente comum, temos a presença de um ou mais <iframe> dentro de uma página. Neste caso quero mostrar que apesar dos <iframe> estarem em uma mesma página, o conteúdo do localStorage e sessionStorage não se misturam, ou seja, eles seguem a regra da origem.

Para simular este cenário utilizei um pequeno código JavaScript executado com o Node.js:

import http from "http";

const server = http.createServer((_, res) => {
  const html = `
      <iframe src="https://designer.mocky.io" frameborder="1"></iframe>
      <iframe src="https://consolelog.com.br" frameborder="1"></iframe>
    `;

  res.writeHead(200, { "Content-Type": "text/html" });
  res.end(html);
});

server.listen(3000, () => {
  console.log("Server is listening on port 3000");
});

exemplo-iframe.js

Para executar o código basta utilizar o comando:

$ node exemplo-iframe.js
Resultado

Ao abrir a página é possível observar pelo menos 3 origens de conteúdo:

  • http://localhost:3000
  • https://consolelog.com.br
  • https://designer.mocky.io

Como o localStorage e sessionStorage são isolados por origem, vamos ter 3 áreas de armazenamento, ilustrados a seguir:

Representação visual do conteúdo HTML e áreas de armazenamento

Importante!
Antes de partimos para os testes de armazenamento, é preciso ter atenção onde seu script será executado no "console" do DevTools. Repare que quando temos um ou mais <iframe> na página, na parte superior do "console" aparece um combo de seleção que indica o contexto onde o código será executado. Veja na imagem abaixo:

Selecionando o contexto de execução do console

Observação: na lista destacada acima há algumas origens além das 3 supracitadas. Estas origens são derivadas do conteúdo do https://consolelog.com.br.

Tomando cuidado com o contexto do "console", executei o seguinte script:

  1. No contexto top salvei uma informação no localStorage
  2. No contexto designer.mocky.io salvei um outro valor no localStorage
  3. No contexto consolelog.com.br novamente salvei outro valor
  4. Por fim consultei na aba "Applicatino" (do DevTools) o conteúdo de cada localStorage

O resultado, como podemos ver abaixo, é que os dados salvos no localStorage não se misturam quando a origem é diferente, mesmo que estejam em um <iframe>. Teríamos o mesmo resultado se tivéssemos utilizado o sessionStorage.

Resultado

Exemplo 3 - diferentes origens e abas/janelas

Um outro cenário é ter várias aplicações que respondem à um mesmo protocolo e domínio, porém em portas distintas, por exemplo, http://localhost:3000 e http://localhost:3001.

Para simular o cenário acima criei uma aplicação em Node.js:

import http from "http";

const porta = process.env.PORT;

const server = http.createServer((_, res) => {
  const html = `Olá, estou executando na porta <strong>${porta}</strong>`;
  res.writeHead(200, { "Content-Type": "text/html" });
  res.end(html);
});

server.listen(porta, () => {
  console.log(`Server is listening on port ${porta}`);
});

index.js

Depois executei dois processos utilizandos as portas 3000e 3001:

PORT=3000 node index.js
PORT=3001 node index.js

Com a aplicação executando em 2 portas, abri 3 janelas no navegador:

  • Janela 1: endereço localhost:3000
  • Janela 2: endereço localhost:3000
  • Janela 3: endereço localhost:3001

Então abri o DevTools para cada janela e executei os comandos que aparecem na imagem abaixo:

Salvando dados no sessionStorage e localStorage em 3 janelas do navegador, onde 2 janelas tem a mesma origem

Veja abaixo o resultado e na sequência a explicação:

Resultado

Para analisar o resultado vamos separar o localStorage do sessionStorage:

localStorage
Já sabemos que os dados do localStorage são compartilhados entre abas/janelas com a mesma origem. Por esta razão as duas primeiras janelas compartilham o mesmo localStorage, então tem exatamente o mesmo valor para a chave mensagem, que é janela2 porta 3000. O primeiro valor que salvamos para esta chave, janela1 porta 3000, foi sobrescrito quando executamos o comando localStorage.setItem('mensagem', 'janela2 porta 3000'); na segunda janela.

Já na janela 3 (localhost:3001), como a origem (a porta é diferente) é diferente das duas primeiras janelas, o valor para a chave mensagem permaneceu como janela3 porta 3001.

sessionStorage
Como citado anteriormente, o sessionStorage não compartilha dados entre janelas/abas mesmo que tenham a mesma origem, então cada janela tem seu próprio sessionStorage.

Apesar de serem diferenças pequenas, saber estes detalhes podem te ajudar bastante.

Exemplo 4 - salvando e consultando objetos

Como já citado, o armazenamento do localStorage e sessionStorage é feito por pares de chave/valor em formato string. Portanto para salvar um objeto é necessário convertê-lo para string utilizando o JSON.stringify:

const dataAtual = new Date('2023-12-01T00:00:00.000Z');
const meuObjeto = { nome: 'ola', data: dataAtual };
localStorage.setItem('dados', JSON.stringify(meuObjeto));

Para resgatar o objeto basta utilizar o JSON.parse:

const meuObjetoResgatado = JSON.parse(localStorage.getItem('dados'));

Aqui vale um grande ponto de atenção: cuidado com o Date. O JSON.stringify converte o valor do objeto Date em uma string no formato ISO 8601. Ao efetuar a operação inversa com o JSON.parse, a string não é convertida em um objeto Date, veja na imagem abaixo:

Salvando e consultando um objeto no localStorage

Neste caso precisamos converter a string meuObjetoResgatado.data em um objeto Date para obter a mesma estrutura do objeto meuObjeto:

const meuObjetoResgatado = JSON.parse(localStorage.getItem('dados'));
meuObjetoResgatado.data = new Date(meuObjetoResgatado.data);

Considerações

Os recursos de armazenamento da web, como localStorage e sessionStorage, são úteis para armazenar dados localmente no navegador do usuário. Com eles, você pode melhorar a experiência do usuário em seu site, armazenando informações e permitindo que o usuário retome onde parou em sua última visita. Lembre-se de que estes recursos têm limitações de tamanho e de que você deve usá-los com cuidado para não sobrecarregar o navegador do usuário e não expor nenhuma informação sensível.

A principal diferença entre o localStorage e o sessionStorage é a maneira como os dados são armazenados. O localStorage armazena dados permanentemente, enquanto o sessionStorage armazena dados temporariamente. Outra diferença importante é que o localStorage é compartilhado entre todas as guias do navegador, enquanto o sessionStorage é limitado à guia atual. Isso significa que, se você armazenar dados no localStorage em uma guia e, em seguida, abrir uma nova guia, os dados armazenados ainda estarão disponíveis. Por outro lado, se você armazenar dados no sessionStorage em uma guia A e, em seguida, abrir uma nova guia B, os dados armazenados na guia A não estarão disponíveis na guia B.

Para não deixar o texto tão extenso, não comentei sobre como enviar/receber dados do localStorage e sessionStorage para/de um <iframe>, mas caso tenha interesse neste cenário, pesquise sobre postMessage. Em um outro momento abordarei exclusivamente este assunto.

Por fim, atualmente todos os navegadores dão suporte ao localStorage e sessionStorage, mas sempre que tiver alguma dúvida com relação aos suportes, sugiro dar uma pesquisada no caniuse.com.

Links interessantes: