APP下载

应用 | Electron:数据存储

原创

Electron

Electron

Electrong数据存储!

计算机程序的本质是算法与数据结构,数据对于任何一个应用程序来说都是核心要素。

例如:对于一个OA应用来说,开发者需要明确用户发起了什么流程,数据应如何保存以及保存在什么地方等等。 这些与数据相关的问题都是值得我们深思熟虑的。

回到Electron应用,它原生就提供了很多API来解决此类问题。

首先,我们先对electron应用数据进行简单地分类:

  • 用户数据;
  • 应用数据。

数据分类

用户数据

  1. 用户数据,即用户的个性化数据,通常来说包括:
  • 用户程序设置;
  • 用户基本信息;
  • 用户使用应用程序所产生的业务数据;
  • ...

注意,这类数据是不建议保存在应用程序的安装目录下的。 应用程序的升级、卸载以及重新安装,该目录通常会被删除,如果用户再次安装应用程序时,就需要重新配置,影响用户体验。

以Windows上的QQ程序为例,我们删除应用程序后,如果没有清理对应的配置和缓存目录,再次安装时,假设之前勾选了「记住密码」选项,应用会自动填充记录的账户和密码。

  1. 这是所有应用程序都面临的问题,因此操作系统为应用程序提供了专有目录来存储应用程序的用户个性化数据:

不同OS的路径不一样:

  • Windows:C:\Users[user name]\AppData\Roaming
  • Mac:/Users/[user name]/Library/Application Support/
  • Linus:/home/[user name]/.config

electorn提供了对应的API来获取此路径:

               
  • 1
app.getPath('userData'); COPY

app.getPath方法传入不同的参数,可以获取不同用途的路径,常见的有:

  • home:用户根目录;
  • desktop:用户桌面;
  • documents:文稿目录;
  • downloads:下载目录;
  • pictures:图片目录;
  • music:音乐目录;
  • video:视频目录;
  • temp:系统临时文件夹路径;
  • exe:当前执行程序的路径;
  • appData:应用程序用户个性化数据的目录;
  • userData:appData路径后加上应用名的路径。

注意,使用node.js的os模块,我们也可以获取系统默认路径。

  1. 操作本地文件,如果需要将用户数据保存的哦磁盘上,它与node.js并没有区别。

文件操作,推荐一个第三方库,fs-extra  它弥补了fs库对文件操作的不足。

应用数据

应用数据,即应用提供了什么样服务,这些服务会转化成对应的数据。这类数据一般存储在服务端,与应用之间通过网络协议进行通信,也可以临时存储在本地应用中。一般来说,这类数据不会总是存储在客户端,因为一旦卸载应用,客户端的数据就被清空。

当然,数据如何存储?最终还是取决于应用程序的类型和真实需求,举个例子:我们想做一个博客类的应用,主要特征:

  • 只给自己看;
  • 可以离线编辑;
  • 联网时能自动备份;
  • ...

一个还不错的解决方案是:实时编辑以及大部分的过往文章都存储在客户端,联网时会定期备份到OSS。

数据持久化

持久化方案的三个方面:浏览器、宿主机本地磁盘以及数据库。

Cookie

  1. 用于存储少量数据,最多不超过4kb。

  2. 通常用来在服务器和客户端间的数据传输,一般情况下浏览器发起的请求都会携带同域下的Cookie数据。

  3. 可以设置有效期,过期后浏览器自动删除。

LocalStorage

  1. 存储在客户端且只能被客户端脚本访问。

  2. 存储限制在2.5M ~ 10M之间,都不超过10M,注意:各个浏览器的限制不一样。

  3. 不能设置过期时间,需要手动删除,否则会一致保存客户端。

4. 在开发Electron应用时,不建议使用LocalStoarge,它的容量限制是很大的硬伤,推荐使用Cookie和IndexedDB。

还有一个可能的问题是,如果使用了自定义协议, 使用localStorage.setItem('myCat', 'Tom')会失效,解决方案和具体原因没有深究,有兴趣的可以去了解下,小编的解决方案是直接使用了electron-store。

Session Storage

它的特性大多与Local Storage相同,唯一不同的是浏览器窗口关闭之后,session storage里的数据将被自动清空 。

应用场景:Electron应用在需要保存程序运行时的临时数据时经常使用到它。

Web SQL

它是一种为浏览器提供的数据库技术,可以使用SQL指令操作数据,该技术已被W3C否决了,了解即可。

IndexedDB

IndexedDB MDN 

  1. 简单理解,IndexedDB就是浏览器提供的本地数据库,可以被网页脚本创建和操作。

  2. 简要讨论下其不足:

  • API设计比较传统,大部分数据读写操作都是异步的;
  • 使用时需要使用大量的回调函数和事件注册函数,没有Promise版本的API可用,导致开发效率并不高。

3.推荐使用第三方封装库:

tips:

  • 这里小编推荐使用Dexie.js;
  • rxdb是一个运行在各大浏览器和Electron内的实时数据库,对于需要向用户显示实时数据的客户端应用来说,它非常有用。
  1. 注意,IndexedDB有版本的概念,它主要解决的一个问题是,如果应用程序有修改数据库的数据结构的需求,如何做数据迁移?

SQLite

  1. SQLite是一个轻型的、嵌入式的SQL数据库引擎。

  2. 它的特点:

  • 自给自足;
  • 无服务器;
  • 零配置;
  • 支持事务。
  1. SQLite是世界上部署最广泛的SQL数据库引擎,大部分桌面应用都使用SQLite在客户端保存数据。

  2. 使用node-sqlite3,命令如下:

               
  • 1
  • 2
  • 3
  • 4
  • 5
npm install sqlite3 --build-from-source --runtime=electron --target=1.7.6 --dist-url=https://electronjs.org/headers # 在MacOS使用Homebrew,使用下面的命令 npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=`brew --prefix` --runtime=electron --target=1.7.6 --dist-url=https://electronjs.org/headers COPY

tips:

  1. node-sqlite3只对SQLite3做了简单的封装,数据的CRUD操作还需要编写传统的SQL语句,开发效率低下。推荐使用knex.js完成业务数据的读写工作。

  2. knex.js

knex.js/github  - 15.7k stars; knex.js/npm 

knex.js是一个SQL指令构建器,可以使用它编写串行化的数据访问代码,它会把这些代码转换成SQL语句,交由数据库执行处理。数据库返回的数据也会被格式化JSON对象。

支持的数据包括:

  • PostgreSQL;
  • MySQL;
  • CockroachDB;
  • SQL Server;
  • SQLite3;
  • Oracle。

tips:knex.js是业务知名的数据库访问工具。

  1. SQLite3的管理工具,推荐使用SQLite Expert 

下载 

特点与不足:

  • 功能丰富,操作简单;
  • 收费,个人版免费;
  • 只支持Windows。

网络服务数据库

  1. 常用的数据库如:
  • MySQL;
  • MongoDB。

第三方库

  1. lowdb(https://github.com/typicode/lowdb) 

它是基于lodash开发的小巧的JSON数据库,可以快速高效地操作数组和JSON对象。

  1. electron-store,是一个专门为Electron设计、依赖少以及轻量的数据库。

electron-store/npm 

支持数据加密,防止数据被恶意窃取, 不需要指定文件的路径和文件名,直接把数据存储在用户的userData目录下。

示例代码:

preload.ts

               
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
import { contextBridge } from 'electron'; contextBridge.exposeInMainWorld('electron', { store: { get(val: any) { return ipcRenderer.sendSync('store-get', val); }, set(property: string, val: any) { ipcRenderer.send('store-set', property, val); }, delete(property: string) { ipcRenderer.send('store-delete', property); }, }, }); COPY

main.ts

               
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
import { ipcMain } from 'electron'; import EStore from 'electron-store'; export const eStore = new EStore(); ipcMain.on('store-get', async (event, val) => { event.returnValue = eStore.get(val); }); ipcMain.on('store-set', async (_event, key, val) => { eStore.set(key, val); }); ipcMain.on('store-delete', async (_event, key) => { eStore.delete(key); }); COPY

service.ts

               
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
export const TOKEN_KEY = '__token__'; export const handleUserResponser = (data: any) => { // window.localStorage.setItem(TOKEN_KEY, data?.token || ''); window.electron.store.set(TOKEN_KEY, data?.token || ''); return data?.token; }; COPY

以Mac为例,数据会自动保存到/Users/[user name]/Library/Application Support/Electron/config.json文件中。

参考资料

  1. IndexedDB MDN 
  2. IndexedDB WangDoc 
  3. 《Electron实战》—— 刘晓伦。
  4. electron-webpack-react-template 

大家加油 :)

评论区

写评论

登录

所以,就随便说点什么吧...

这里什么都没有,快来评论吧...