Home > Software engineering >  Expose NodeJS Methods (FS) in Electron Renderer
Expose NodeJS Methods (FS) in Electron Renderer

Time:12-14

I am using Quasar v2 for my Electron app development.

In this version, native node modules will no longer work on the renderer processes.

To get around this, there is electron-preload.js where we can access these node methods and expose them to the other parts of the app.

So I did this to expose fs:

import { contextBridge } from 'electron'
contextBridge.exposeInMainWorld('electronFs', require('fs'))

Then on my Vue/js files:

const fs = window.electronFs || require('fs')
fs.lstatSync(somePath).isFile()

But then I am getting fs.lstatSync(...).isFile is not a function. Any thoughts how can I make this work?

This is just for a local application (no web connectivity).

Thanks!

CodePudding user response:

That happens because, in Electron, the backend and the UI don't share the same process (they run in different threads) because if you allow exposing native node APIs into the user context (the UI that runs finally in Chromium), it means that any time external javascript is loaded, they can access all those native APIs in the user computer.

So, those variables get transported to one thread to the other using IPC (Inter-process Communication), is just data, need to be primitives, if not they get serialized to primitives in the end (types of variables with no methods or objects like string, numbers, dates, or objects as string or binary), so probably to send those object from the parent context to the UI context Electron probably removes all non-serializable properties (so no functions).

Don't do that, is extremely insecure, just move data from one side to the other, which is very similar to using WebSockets.

CodePudding user response:

By default, Main process doesn't share the same context as Renderer's. And Preload runs in a context of Renderer's but isolated. Instead of exposing native Nodejs APIs to Renderer insecurely, even though you're building a local app, you may still use IPC to expose limited interfaces to Preload of Renderer process, then use contextBridge to expose APIs to Renderer. Here are some demo snippets.

/* Main.js */

const fs = require('fs');
const {ipcMain} = require('electron');

ipcMain.handle('isFile', (path) => 
    fs.lstatSync(path).isFile()
)
/* Preload.js */

import {ipcRenderer, contextBridge} from "electron";

contextBridge.exposeInMainWorld('myAPIs', {
isFile: (path) => ipcRenderer.invoke('isFile')
}

/* index.vue */

myAPIs.isFile('path-to-file');
  • Related