Electron
is a great framework to build cross-platform applications. With Electron, we can easily build the desktop application by using web techniques.
Using Electron can let us easily create cross-platform applications on top of web technologies. Since Electron app is still kind of web app, when talking about storing data, we are used to storing the data in remote servers via sending HTTP requests.
What if I want to store the data locally?
In this article, I will share my experience in building an Electron application with persistent local data storage.
Browser localStorage: Electron is built on Chromium, that is browser localStorage is well supported.
electron-store
: For simple scenarios, just go for electron-store. The API is easy to use
Considering storing your data in the SQL or NoSQL like database would be a better idea when use cases are a bit complicated.
After doing some researches and leveraging between SQL and NoSQL with Electron, I end up going to NoSQL solution.
I am going to introduce the way to integrate
nedb
with your Electron app.
As NeDB doc said, NeDB is
Embedded persistent or in memory database for Node.js, nw.js, Electron and browsers, 100% JavaScript, no binary dependency. API is a subset of MongoDB's and it's plenty fast.
I am significantly pleasure using NeDB to build my production-ready product.
To help you understand the idea quickly, let's use
electron-quick-start
template and have the quick experience
Follow the installation instruction:
# Clone this repository$ git clone https://github.com/electron/electron-quick-start
# Go into the repository$ cd electron-quick-start
# Install dependencies$ npm install# Run the app$ npm start
Create a db folder. Then, create schemas and stores folder under db.
The repo should look like:
├── LICENSE.md
├── README.md
├── db
│ ├── schemas
│ └── stores
├── index.html
├── main.js
├── package-lock.json
├── package.json
├── preload.js
└── renderer.js
Enter fullscreen modeExit fullscreen mode
nedb-promises is a wrapper around nedb. With promise can save you tons of time to handle the callback.
$ yarn add nedb-promises
Enter fullscreen modeExit fullscreen mode
ajv is a JSON schema validator library. Schema validator is optional to build the NoSQL database, but I'd recommend using it since well-defined schema and validator can bring better maintainability.
NIT: You can also replace ajv to your preference schema validator
$ yarn add ajv
Enter fullscreen modeExit fullscreen mode
Let's destruct the component of a todo list app.
A todo list app should have a list of todo item. A simple todo item would include todo content, is it finished?
Since the goal of the article is sharing the way to integrate NeDB with Electron, I won't elaborate the API of NeDB too much. You can get the idea first and spend some time to go through the NeDB afterwards.
Worth noticing, we init the class when exporting the module. This tactic help you to keep one Store instance across the application.
Since this is a simple example, there is only one store. In real-world cases, you can use the same structure to extend the application.
Integrate everything
So far, we've finished all works for controlling the database. The repo should look like: ├──LICENSE.md├──README.md├──db│ ├──schemas│ │ └──todoItem.js│ └──stores│ └──todoItem.js├──index.html├──main.js├──package.json├──preload.js├──renderer.js└──yarn.lockEnter fullscreen modeExit fullscreen mode
// Modules to control application life and create native browser windowconst{app,BrowserWindow}=require('electron')constpath=require('path')constdb=require('./db/stores/todoItem');global.db=db;functioncreateWindow(){// Create the browser window.constmainWindow=newBrowserWindow({width:800,height:600,webPreferences:{nodeIntegration:true,mainWindow.loadFile('index.html')...thesame...Enter fullscreen modeExit fullscreen mode
So we can start to add the view logic. I will skip the explanation of the View layer, since there are many ways to do that.
The final implementation
Electron doesn't have the strict limitation of data flow. You can store the data in localStorage, or store the data in main thread and expose it to global. Or, you can also use electron-store for simple key-value storage.
When the application grows bigger and bigger, the data flow will become harder to maintain. You may have a copy in localStorage, and if you are using client state management framework, like redux, client side will also have another copy.
The data flow will become a mess without proper data flow.
The demo is a simple case. In the real world case, you can add cache to improve the performance, or add more validation to secure the db access.
Plus, NeDB always stores the data in a text file, so it's straightforward to realize data import/export.
There is a new package to store data in electron as JSON files. The beautiful thing about this package is that it allows you to encrypt your data and you can store different kinds of data each one with its file and also there no API to get and set the data. You can manipulate your data with vanilla Javascript, also your data is watched which means the data will be written to a JSON file in every change