sindresorhus / electron-store

Simple data persistence for your Electron app or module - Save and load user preferences, app state, cache, etc
MIT License
4.61k stars 150 forks source link

Store does not work in renderer process #268

Open pparh602 opened 1 year ago

pparh602 commented 1 year ago

I've electron app with Angular frontend. I'm trying to use Store in the renderer process as described in the README file

Here is my code for preload and electron-main.js: preload.js file:

const { ipcRenderer, contextBridge } = require("electron");
const Store = require("electron-store");

const store = new Store({
  encryptionKey: "my-secret-encryption-key",
});

electron-main.js file:

const Store = require("electron-store");
Store.initRenderer();

const createWindow = () => {
  win = new BrowserWindow({
    width: 400,
    height: 600,
    autoHideMenuBar: true,
    webPreferences: {
      preload: path.join(__dirname, "./src/app/app-preload.js"),
    },
  });
  win.loadURL("http://localhost:4200/"); // For local development builds
};
app.whenReady().then(() => {
  createWindow();

  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

When I use Store in above way I got the error: Unable to load preload script: /home/Documents/todo-desktop/src/app/app-preload.js (anonymous) @ VM4 sandbox_bundle:2

VM4 sandbox_bundle:2 Error: module not found: electron-store at preloadRequire (VM4 sandbox_bundle:2:82751) at :3:15 at runPreloadScript (VM4 sandbox_bundle:2:83503) at VM4 sandbox_bundle:2:83762 at VM4 sandbox_bundle:2:83917 at _electron_webpack_init (VM4 sandbox_bundle:2:83921) at VM4 sandbox_bundle:2:84044 (anonymous) @ VM4 sandbox_bundle:2

As soon as I remove Store from preload.js file, I didn't get any error.

NoumanSaleem commented 11 months ago

module not found seems odd. Though if using Election >= 20.0, you'll need to disable sandbox for webPreferences if you want to use electon-store.

e.g

    webPreferences: {
      ...,
      sandbox: false,
    },

https://www.electronjs.org/blog/electron-20-0#default-changed-renderers-without-nodeintegration-true-are-sandboxed-by-default

nateclonch commented 6 months ago

I'm getting the same issue, but I have nodeIntegration enabled, which disables sandbox. This error only showed up after updating electron and electron forge.

Enubia commented 6 months ago

I have a somewhat similar issue, after I upgraded to Electron v30 my Vue application doesn't have access to the store anymore. Downgrading to the last v29 version of Electron fixed it for the time being

nateclonch commented 6 months ago

When I encountered this issue, it was because I was passing Electron Store directly through to the renderer process via contextBridge.exposeInMainWorld in the preloader, I think exposing security risks from packages like FS and OS. I ended up having to isolate Electron Store to the main process and send all my requests through ipcRenderer/ipcMain. The error message went away once Electron Store and its dependencies were isolated to the main process.

In other words, instead of writing this in your preload.js:

const Store = require('electron-store');
const store = new Store();

contextBridge.exposeInMainWorld('store', store);

You should instead approach it like this in your preload.js:

const { ipcRenderer } = require('electron');
const storeSend = (action, key, value) => ipcRenderer.sendSync('store-send', { action, key, value });

contextBridge.exposeInMainWorld('store',
  {
    get: key => storeSend('get', key),
    set: (key, value) => storeSend('set', key, value),
  }
);

Then something along these lines in your main process:

const { ipcMain } = require('electron');
const Store = require('electron-store');
const store = new Store();

ipcMain.on('store-send', (event, params) => {
  const { action, key, value } = params;

  switch (action) {
    case 'get':
      event.returnValue = store.get(key);
      break;

    case 'set':
      event.returnValue = store.set(key, value);
      break;
  }
});

You will also need to deal likewise with any other packages that shouldn't be exposed to the renderer process.