npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

awesome-storage-manage

v0.2.0

Published

- 有直接调用原生setItem/getItem的 - 也有自己封装了一套方法的 - 还有使用工具sdk方法的

Downloads

4

Readme

awesome-storage-manage:前端存储管理方案

一、项目当前痛点

1. 存/取storage方法各式各样

  • 有直接调用原生setItem/getItem的
  • 也有自己封装了一套方法的
  • 还有使用工具sdk方法的

需要统一存取的方法,减少后续维护成本

import AwesomeStorage from 'awesome-storage-manage';

// 白名单
const whitelist = [
  'SLARDARnovel_author_i18n',
  '__tea_cache_tokens_4793',
  'mue_first_load_novel_author_i18n_cdn',
];

// 白名单正则
const whitelistRegExps = [
  /happy_debug/,
  /text./,
  /version./,
  /pia_/,
  /mue_first_load/,
  /SLARDAR/,
  /tea_cache/,
];

const myLocalStorage =  new AwesomeStorage(whitelist, whitelistRegExps);

// 存
myLocalStorage.setItem('xxxx-key-xxxxx', value, {schedule: 1});

// 取
myLocalStorage.getItem('xxxx-key-xxxxx');

2.存储storage格式不规范

需要定义 Storage 存储结构,在存储值的基础上,增加额外字段,用于支持自定义的管理能力。

 /**
* 存储项结构,默认对外暴露具体「格式化的值」,使用者不需关心具体设置
*/
interface AwesomeStorageItem {
  /** 存储的值,传入和传出的都是格式化的值 */
  value: any;
  /** 具体过期时间,unix时间戳 */
  expire?: number;
  /** 续期制周期,旧数据默认周期是 s,存在周期一定存在具体过期时间 */
  schedule?: AwesomeStorageSchedule;
  /** 是否只使用1次,一旦有取值操作,该项立即销毁 */
  once?: boolean;
}

3. 历史数据需要转化处理

之前的历史storage存储格式需要转化成规范的形式。

首次运行时,做历史数据转换,后续不再重复处理。

/** 已转换的标识 */
const convertedKey = 'awesome_storage_converted';

/** 应用冷启动时初始化项目本地存储 */
  init() {
  // 执行一次清理
  if (
    this.originTarget.getItem(cleanCycleKey) &&
    Number(this.originTarget.getItem(cleanCycleKey)) +
      this.cleanCycle * 24 * 3600 >=
      Math.floor(new Date().getTime() / 1000)
  ) {
    this.clean();
  }
  if (this.originTarget.getItem(convertedKey)) {
    this.hasConvert = true;
    return;
  }
  // 如果未格式化则启动预处理
  this.normalize();
}

/** [私有方法] 标准化本地存储 */
private normalize() {
  const savedList = this.getNormalizedItems();
  savedList.forEach(([key, value]) =>
    this.setItem(`${this.workspace}_${key}`, value, { schedule: AwesomeStorageSchedule.small }),
  );
  // 存转化标识key
  this.setItem(convertedKey, true);
  // 存cleanCycle时间戳
  this.setItem(cleanCycleKey, Math.floor(new Date().getTime() / 1000));
  this.hasConvert = true;
}

4. 无storage清除/续期机制

历史存入的storage有些长期用不到,日积月累后,占据了用户设备大量的存储空间。

需要添加项目定期清除storage机制,以及经常访问的storage续期增加存储时间的机制。

  • 清除机制

    • 在项目启动时候,到达了清除事件周期就执行清除
  • 续期机制

    • 在getItem时,如果有续期周期则给item时间戳续期

二、使用方法

1. 初始化

  • 可传入白名单列表,包含此这些string的storage不会被自动转换,针对一些sdk内置storage存储的情况

    • whitelist?: string[]
  • 可传入白名单正则列表,匹配这些正则的storage不会被自动转换,针对一些sdk内置storage存储的情况:

    • whitelistRegExps?: RegExp[]
  • 可传入项目启动时清除过期storage的周期,默认为10天

    • cleanCycle?: number
  • 可传入workspace,项目的前缀标识,针对同一域名下不同项目使用同一key的情况,可以加上前缀来区别

    • workspace?:string
  • 可传入构造函数localStorage or sessionStorage, 默认是 localStorage

import AwesomeStorage from 'awesome-storage-manage';

// 白名单
const whitelist = [
  'SLARDARnovel_author_i18n',
  '__tea_cache_tokens_4793',
  'mue_first_load_novel_author_i18n_cdn',
];

// 白名单正则
const whitelistRegExps = [
  /happy_debug/,
  /text./,
  /version./,
  /pia_/,
  /mue_first_load/,
  /SLARDAR/,
  /tea_cache/,
];

const myLocalStorage =  new AwesomeStorage(whitelist, whitelistRegExps,20, 'your_own_project');

2. 清除/历史storage转化机制

 // 转化历史不规范的storage & storage过期清除
myLocalStorage.init();

// 具体方法
/** 应用冷启动时初始化项目本地存储 */
init() {
  // 执行一次清理
  if (
    this.originTarget.getItem(cleanCycleKey) &&
    Number(this.originTarget.getItem(cleanCycleKey)) +
      this.cleanCycle * 24 * 3600 >=
      Math.floor(new Date().getTime() / 1000)
  ) {
    this.clean();
  }
  if (this.originTarget.getItem(convertedKey)) {
    this.hasConvert = true;
    return;
  }
  // 如果未格式化则启动预处理
  this.normalize();
}



/** [私有方法] 清理本地存储中过期的项,通常在冷启动是异步处理 */
private clean() {
  this.setItem(cleanCycleKey, Math.floor(new Date().getTime() / 1000));
  const list = this.getNormalizedItems();
  list.forEach(([key, item]) => {
    const normalized = this.parse(item);
    if (!(normalized && this.checkExpire(normalized))) {
      this.removeItem(key);
    }
  });
}

/** [私有方法] 标准化本地存储 */
private normalize() {
  const savedList = this.getNormalizedItems();
  savedList.forEach(([key, value]) =>
    this.setItem(key, value, { schedule: AwesomeStorageSchedule.small }),
  );
  // 存转化标识key
  this.setItem(convertedKey, true);
  // 存cleanCycle时间戳
  this.setItem(cleanCycleKey, Math.floor(new Date().getTime() / 1000));
  this.hasConvert = true;
}

/** [私有方法] 获取已格式化的值列表 */
private getNormalizedItems(): [string, string][] {
  return Object.entries(this.originTarget).filter(
    ([key]) =>
      !this?.whitelist?.includes(key) &&
      !this?.whitelistRegExps?.some(reg => reg.test(key)),
  );
}

3. 续期机制

 /** 读取 key 对应的值,读出的值已经过序列化 */
getItem(key: string, defaultValue?: any) {
  const data = this.originTarget.getItem(key);
  const normalized = this.parse(data);
  // 仅用一次的值,用完销毁
  if (normalized?.once) {
    this.removeItem(key);
  }
  // 续期再存
  if (normalized?.schedule) {
    const currentDate = new Date();
    currentDate.setMonth(currentDate.getMonth() + normalized.schedule);
    const unixTimestamp = Math.floor(currentDate.getTime() / 1000);
    this.save(key, {
      ...normalized,
      expire: unixTimestamp,
    });
  }
  return normalized?.value ?? defaultValue;
}

三、API

import AwesomeStorage from 'awesome-storage-manage';

// 白名单
const whitelist = [
  'SLARDARnovel_author_i18n',
  '__tea_cache_tokens_4793',
  'mue_first_load_novel_author_i18n_cdn',
];

// 白名单正则
const whitelistRegExps = [
  /happy_debug/,
  /text\./,
  /version\./,
  /pia_/,
  /mue_first_load/,
  /SLARDAR/,
  /tea_cache/,
];

const myLocalStorage =  new AwesomeStorage(whitelist, whitelistRegExps);

// 初始化(转化历史不规范的storage & storage过期清除)
myLocalStorage.init();

// 存
myLocalStorage.setItem('xxxx-key-xxxxx', value, {schedule: 1});

// 取
myLocalStorage.getItem('xxxx-key-xxxxx');

// 存一次就清除
myLocalStorage.setItemOnce('xxxx-key-xxxxx', value);

// 清除
myLocalStorage.removeItem('xxxx-key-xxxxx');

// 全部清除
myLocalStorage.clear();

四、npm包

欢迎使用,已在多个大型业务落地