Как разместить ваше localStorage в том же домене…

TL;DR

  • Локальное хранилище подвержено конфликтам имен и случайному переопределению данных
  • Общий объем данных, которые могут быть сохранены, ограничен для каждого домена.

persistme позволяет вам использовать пространство имен для вашего локального хранилища несколькими приложениями и игнорировать ограничение на размер, применяя сжатие к вашим данным.

localStorage был отличным дополнением к API веб-хранилищ, позволяя разработчикам сохранять некоторые данные для улучшения взаимодействия с пользователем. Он существует давно, и сегодня почти каждое веб-приложение использует эту технологию для сохранения некоторых взаимодействий с пользователем и многого другого. Однако из-за того, что Интернет процветает, и все традиционные настольные приложения либо ушли на пенсию, либо теперь предлагают столь же привлекательный и сложный веб-интерфейс, в локальном хранилище возникли два неотложных ограничения, которые я осознал.

  • Невозможность разделить использование нескольких приложений в одном домене
  • Ограниченный лимит данных

Давайте поговорим о решениях этих двух проблем.

Использование нескольких приложений в одном домене

Поскольку localStorage хранит пары ключ-значение, зависящие от домена, вы быстро столкнетесь с проблемами, если разместите несколько приложений в одном домене, все из которых используют локальное хранилище для хранения некоторых данных, относящихся к их приложениям. Вы спросите, зачем мне размещать несколько приложений в одном домене? Что ж, посмотрите на любую крупную организацию, есть вероятность, что у них есть распределенные команды, каждая из которых заботится об одном аспекте большого приложения, ориентированного на пользователя.

Например, возьмем случай с веб-сайтом электронной коммерции. Были бы группы, которые будут заботиться о своих целевых страницах, одна группа - для страницы с подробностями о продукте, другая - для каталога продуктов, третья - для их оплаты и т.д. , /product/{id}, /payment и т. Д.

Неудивительно, что каждая из этих команд может случайно наступить на место друг друга при хранении / извлечении данных с помощью localStorage.setItem(key, value) и localStorage.getItem(key). Использование того же ключа, что и в других приложениях, но с совершенно другим контекстным значением, может означать сломанный или, что еще хуже, поддельный пользовательский интерфейс.

Более того, даже если ваши приложения размещены на разных поддоменах, есть вероятность, что вы устанавливаете домен как корневой домен своего приложения, чтобы обойти ограничения политики одинакового происхождения. Таким образом, ваш localStorage будет вести себя так, как если бы он находился в корневом домене, возвращая вас к основной проблеме.

Решение

Простым решением этой проблемы является добавление перед всеми ключами вашего приложения уникального имени проекта к префиксу и последующее сохранение / извлечение значений с использованием этих ключей. У каждой компании есть внутренние кодовые имена репозиториев проектов, которые должны совпадать с вашим localStorage идентификатором.

// APP 1
const APP_NAME = 'PROJECT_NAME_1';
localStorage.setItem(`${APP_NAME}.userSetting`, 'AWESOME 1');
localStorage.getItem(`${APP_NAME}.userSetting`); // AWESOME 1
// APP 2
const APP_NAME = 'PROJECT_NAME_2';
localStorage.setItem(`${APP_NAME}.userSetting`, 'AWESOME 2');
localStorage.getItem(`${APP_NAME}.userSetting`); // AWESOME 2

Вы можете подумать, что делать это каждый раз, когда вы хотите использовать localStorage методы, чревато ошибками и проблематично. Что ж, в идеале вы должны создать оболочку и использовать ее вместо прямого доступа к объекту localStorage.

// AppStorage.js
const APP_NAME = 'PROJECT_NAME';
const getKey = key => `${APP_NAME}.${key}`;
export const set = (key, value) =>
    localStorage.setItem(getKey(key), value);
export const get = key =>
    localStorage.getItem(getKey(key));
// other wrapper methods
...
// SomeModule.js
import * as AppStorage from './appstorage';
AppStorage.set('userSetting', 'AWESOME');
AppStorage.get('userSetting') // AWESOME

Как вы понимаете, этот простой, но мощный метод может помочь вам избежать случайных производственных ошибок, вызванных конфликтами имен и случайными переопределениями.

Ограниченный лимит данных

Мне не нужно это подробно объяснять. Существует предел того, сколько данных вы можете втиснуть в это локальное хранилище для домена. Каждый браузер имеет свой предел и удаляет данные с помощью определенных политик. Обычно лимита хватает на нормальные случаи. Однако, если ваше приложение в значительной степени полагается на локальное хранилище для кэширования / сохранения данных пользователя и / или данных приложения для беспрепятственного взаимодействия с пользователем, вы можете столкнуться с проблемами, когда ваши данные либо очищаются, либо не разрешаются для дальнейшего хранения браузером, если вы превысите свой лимит. .

Решение

Перед сохранением данных в локальном хранилище используйте алгоритм сжатия на стороне клиента, например сжатие на основе lz. Накладные расходы на производительность незначительны, но прирост данных значительный, и вы сможете втиснуть гораздо больше, чем в идеале.

...
// building on to previous example
import LZString from 'lz-string';
const { compress, decompress } = LZString;
export const set = (key, value) =>
    localStorage.setItem(getKey(key), compress(value));
export const get = key =>
    decompress(localStorage.getItem(getKey(key)));
...

Я написал небольшую (~ 2 КБ) JS-библиотеку с открытым исходным кодом, persistme, которая включает решение обеих этих проблем, включая несколько приятных вещей для некоторых распространенных случаев использования локального хранилища. Проверьте это и проявите немного любви, если хотите :)

import { createStorage, createSetting } from 'persistme';
const AppStorage = createStorage('MY_APP1',
    {/*optional defaults*/});
AppStorage.get('theme'); // returns default value if provided
AppStorage.set('theme', 'blue');
AppStorage.get('theme'); // blue
// or even simpler
const UserSetting = createSetting({ storage: AppStorage });
console.log(UserSetting.theme); // blue
UserSetting.theme = 'red';
console.log(UserSetting.theme); // red


Попробуйте и благословите меня позже;)