GithubHelp home page GithubHelp logo

naver / egjs-persist Goto Github PK

View Code? Open in Web Editor NEW
42.0 16.0 10.0 1.65 MB

Provide cache interface to handle persisted data among history navigation.

Home Page: https://naver.github.io/egjs-persist/

License: MIT License

JavaScript 95.55% HTML 4.45%
cache egjs persist bfcache storage

egjs-persist's Introduction

egjs-persist npm version Build Status Coverage Status

Provide cache interface to handle persisted data among history navigation.

Documents

Download and Installation

Download dist files from repo directly or install it via npm.

For development (Uncompressed)

You can download the uncompressed files for development

For production (Compressed)

You can download the compressed files for production

Installation with npm

The following command shows how to install egjs-persist using npm.

$ npm install @egjs/persist

How to use

import Persist from "@egjs/persist";

const persist = new Persist(key);

// Get information about that page.
const aInfo = persist.get("a");

// Set information about that page.
persist.set("a", "aa");

// Remove information about that page.
persist.remove("a");

Handle the error

If the information stored in Persist exceeds the storage quota, a PersistQuotaExceededError error occurs.

The template of the error message is as follows.

Uncaught PersistQuotaExceededError: Setting the value (size: 000) of 'Key' exceeded the SessionStorage's quota. The highest values of SessionStorage are {"key0":0}, {"key1":0}, {"key2":0}.

If you handle the error, you can check the storage information, the key you want to save, and the size of the information.

import Persist, { PersistQuotaExceededError } from "@egjs/persist";

const persist = new Persist(key);

try {
    // Get information about that page.
    const aInfo = persist.get("a");

    // Set information about that page.
    persist.set("a", "aa");

    // Remove information about that page.
    persist.remove("a");
} catch (e) {
    if (e instanceof PersistQuotaExceededError) {
        console.log(e.key, e.size);
    }
}

Used in SPA

We cannot detect changes in history. The entity using the SPA must respond to changes.

Vanilla

import { updateDepth, replaceDepth } from "@egjs/persist";

// use pushState function
const orgPushState = history.pushState;

Object.defineProperty(history, "pushState", {
    configurable: true,
    value: (...args) => {
        orgPushState.call(history, ...args);
        updateDepth();
    },
});

// or
history.pushState("/aa", "title", {});
updateDepth();

// use replaceState function
const orgReplaceState = history.replaceState;

Object.defineProperty(history, "replaceState", {
    configurable: true,
    value: (...args) => {
        orgReplaceState.call(history, ...args);
        replaceState();
    },
});

// or
history.replaceState("/aa", "title", {});
replaceDepth();

React

import React, { useEffect } from "react";
import { Router } from "react-router-dom";
import { createBrowserHistory } from "history";
import { updateDepth } from "@egjs/persist";

const customHistory = createBrowserHistory();

export default function App() {
    useEffect(() => customHistory.listen(() => {
        updateDepth();
    }), []);
    return (
    <Router history={customHistory}>
        ...
    </Router>
  );
}

Vue

import VueRouter from "vue-router";
import { updateDepth } from "@egjs/persist";

const router = new VueRouter();

router.afterEach(() => {
    updateDepth();
});

Supported Browsers

The following are the supported browsers.

Internet Explorer Chrome Firefox Safari iOS Android
9+ latest latest latest 7+ 2.3+ (except 3.x)

How to start developing egjs-persist?

For anyone interested to develop egjs-persist, follow the instructions below.

Development Environment

1. Clone the repository

Clone the egjs-persist repository and install the dependency modules.

# Clone the repository.
$ git clone https://github.com/naver/egjs-persist.git

2. Install dependencies

npm is supported.

# Install the dependency modules.
$ npm install

3. Build

Use npm script to build eg.Persist

# Run webpack-dev-server for development
$ npm start

# Build
$ npm run build

# Generate jsdoc
$ npm run jsdoc

Two folders will be created after complete build is completed.

  • dist folder: Includes the persist.js and persist.min.js files.
  • doc folder: Includes API documentation. The home page for the documentation is doc/index.html.

Linting

To keep the same code style, we adopted ESLint to maintain our code quality. The rules are modified version based on Airbnb JavaScript Style Guide. Setup your editor for check or run below command for linting.

$ npm run lint

Test

Once you created a branch and done with development, you must perform a test running npm run test command before you push code to a remote repository.

$ npm run test

Running a npm run test command will start Mocha tests via Karma-runner.

Bug Report

If you find a bug, please report it to us using the Issues page on GitHub.

License

egjs-persist is released under the MIT license.

Copyright (c) 2015 NAVER Corp.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

egjs-persist's People

Contributors

alwaysawake avatar arkist avatar daybrush avatar godsenal avatar happyhj avatar qpitlove avatar sculove avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

egjs-persist's Issues

If you set no value and get no value, you return null unconditionally.

If you set no value and get no value, you return null unconditionally.

persist.set("a", "");
persist.set("b", 0);
persist.set("c", null);
persist.set("d", undefined);

persist.get("a"); // null, but ""
persist.get("b"); // null, but 0
persist.get("c"); // null
persist.get("d"); // null

Use document.referrer as a key on history management.

Currently only URL is used as a key for different page. and URL is added on depths arrays. But It has some problem. it could have too many duplication of URL. So it removes previous URL and just adds new depth. For example,

  • A(1) -> B(2) -> C(3) -> D(4) -> A(5)

() means a depth.

Then history will be B -> C -> D -> A and it make problem when you go back to previous A and navigates to other sites. For example, A-> E... In this situation B-> C->D should be removed. But depth of A (5) is bigger than B, C, D(2, 3, 4).

To supplement this, we can use document.referrer with URL. It makes possible that A(1) followed by none can be distinguished by A(5) followed by D(4).

For example,

  • A(1) -> A-B(2)-> B-C(3) ->C->D(4) -> D->A(5)

And also it could manage history more correctly. For example if persist is not applied on page A, and You navigate like follows you could make depths unintended way.

  • A -> B , and Back
  • A -> C

Then B -> C is the depths of this history. But If you add A (referrer) on a history then you can acquire depth like A->C as you intended.

JS-only 360degree car demo

Hi

The 360-degree demo on egjs is one of the most performant ones of any JS library out there. Is there a demo / reference of the 360-degree code without a JQuery dependency?

Support hash

I hope that the information stored and read is different according to the hash.

Missing devDeps: eslint-plugin-import

> eslint src


Oops! Something went wrong! :(

ESLint couldn't find the plugin "eslint-plugin-import". This can happen for a couple different reasons:

1. If ESLint is installed globally, then make sure eslint-plugin-import is also installed globally. A globally-installed ESLint cannot find a locally-installed plugin.

2. If ESLint is installed locally, then it's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

    npm i eslint-plugin-import@latest --save-dev

If you still can't figure out the problem, please stop by https://gitter.im/eslint/eslint to chat with the team.

Remove useless page state(information)

I am using the state save / restore module to restore the state like BFCache provided by Safari. However, there is an issue that uses space unnecessarily. I have tried to solve this problem, but I am not satisfied with it.

Overview and Problems of Current Modules

We have created a module to remember the previous state when moving to the previous or next page in the history of the page.

This feature is one of the functions that are required quite a lot in the multiple page based service. That is, when you press the Back button or the Forward button, you want to restore the previous state to improve usability. For example, the scroll position is the most representative state. In addition, the position of the carousel shown in the page can also be restored. In the Safari browser, BFCache provides this functionality.

On the PC, Android Chrome, the Back button does not restore the previous page when you go to the previous page by pressing the Back button, so you can use this module (internally using session storage) to save the state to be restored on the page, When you return to the page, it recalls the saved state.

However, the current implementation is a big problem. As you move through the page, the stored status values will not be deleted and will continue to accumulate. Because there is a limit to the storage space (2MB ~ 10MB), there is an issue that exceeds the storage space.

AS IS

image

TO BE

  • When the page is moved, unnecessary storage information is deleted based on the current page.

image

Difficulty in solving problems

To solve this problem, a method for deleting unnecessary data is required.

To eliminate unnecessary state values, the method you want to implement is as follows.

Removes the status of unnecessary pages from the session storage when the previously moved pages are excluded from the target to move back or forward based on the current page. For example, if you move from A page to B page and then back to C page again, page B is not available for Back or Forward. Therefore, the status information of the page is cleared.

This implementation maps the depth information to each page movement path. If the depth of the newly moved page is less than or equal to the existing page depth, existing page information existing below the depth is deleted.

However, I encounter some difficulties.
   1. No Browser API to know depth information
   2. Can not use or update history state information
       - history.state can be overwritten arbitrarily on each page
   3. The history length that will be the basis of the depth value is maximum length is 50 (based on Chrome).
   4. Can not distinguish whether navigation is Back or Forward.
   5. Long press on the Back / Forward button, as well as previous page navigation, allows you to skip several steps.

Incomplete alternative

So I thought about how to calculate the virtual depth based on the page URL.

That is, we add depth every time we move to a new page. For example, if you move in the order of A -> B -> C, you can randomly assign depths of 1, 2, and 3, respectively.

However, this alternative also faces two problems:

   1. A -> B -> C -> A (each moved to a new page), A state value will be overwritten.
   2. A -> B -> C -> A -> D (each moved to new page) You can not know the depth of current A(1st or 4th) if you move the steps through the long press of the Back button.

History.state cannot be used

In this situation, it is possible to compensate in the following way, but it is not a perfect solution either.
      - You can complement the history length value by creating a key for each page in combination with a URL, but if you go beyond 50, the same problem occurs.
      - The possibility of duplication can not be avoided even though the key to the page is combined with the URL to Referrer.

I am currently working on the issue above, but I would like to ask you further advice.

Implement api using path parameter

Description

motivation

The setter always need the entire object,
In this way, you can not avoid unnecessarily long code.

// Current
const state = eg.Persist("key");
state.foo.bar = false;
eg.Persist("key", state);

// New api
eg.Persist.set("key", "list.0", false);
// or
const persist = new eg.Persist("key");
persist.set("list.0", false);

spec

  1. Can create instance with key string.
var persist = new eg.Persist("key");
  1. Can use path parameter on both static and instance method.
    Use dot notation.
// instance method
persist.get("foo.bar");
persist.set("foo.bar", 1);

// static method
eg.Persist.set(key, 'foo.0.bar', 'b'); // use number to access item in array
  1. Set method should return self for method chaining.
persist.set("foo.bar.zoo", 20)
       .set("foo.zoom.zoo", 10)
       .set("foo.too.zoo", 10);

How about process `scrollRestoration` property in Persist?

@sculove commented on Thu Dec 29 2016

Description

The persist create the virtual bfcache (?).
When history back, the scroll position is moved by browser like chrome.
How about control scrollRestoration property?

if ('scrollRestoration' in history) {
  // Back off, browser, I got this...
  history.scrollRestoration = 'manual';
}

@netil commented on Wed Jan 04 2017

  • Pros: Don't intervene programmatically scroll action.
  • Cons: If restoration is set to manual, it means need to implement scroll restoration programmatically.

@sculove commented on Wed Jan 04 2017

I think if you are using persist, it will be the user who will want to control the scrolling


@netil commented on Wed Jan 04 2017

But, in other word it's unnecessary handle scroll (for that it should check exact restoration happening natively)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.