5

Currently I am playing around with electron using vue-cli-plugin-electron-builder along side a simple vue project. This is the project https://github.com/nklayman/vue-cli-plugin-electron-builder .

   vue create my-project
   cd my-project
   vue add electron-builder
   npm run electron:serve

My goal is to add a simple plugin-like architecture. The app serves only base functionality but can be extended with "plugins". Those plugins therefore are not included in the built, but will be loaded at runtime by electron. I would prefere when those plugins just behave like node modules ( module.exports = ) with its own dependencies ( probably with a package.json file inside ). I would locate those plugins at app.getPath('userData') + '/Plugins.

I looked at a few approaches on how to tackle this problem :


1. Using Nodejs vm module

First, I tried using Nodejs vm module to read and execute a script from an external file, all at runtime. It works great so far, although I would not be able to use external dependencies inside those loaded scripts. If I want to use external dependencies inside the plugin scripts, those dependencies must have been included in the electron build beforehand. Somehow defeats the whole purpose of having plugins ... only vanilla js + nodejs base modules would be possible .


2. using global.require

I saw this solution in another SO answer.

They say to use global.require but it throws an error saying global.require is not a function. The solution looked promising first, but somehow I can't get it to work.


3. simply use require

Of course I had to try it. When I try to require an external module from a non-project location it won't find the module, even if the path is correct. Again, the path I am trying to locate the module should be at app.getPath("userData"), not in the projects root directory. When however, I locate the plugins inside the root directory of the project it gets included in the built. This again defeats the purpose of having plugins.


Goal

So far, I haven't found a viable solution to this. I simply want my electron app to be extendible with basic node modules at runtime ( following a pre-defined schema to simplify ) . Of course there is atom, made with electron, using their own apm manager to install and load plugins, but this seems way to overpowered. Its enough for me to only have plugin files located locally, to have a public "marketplace" is no goal. Also, it's ok if the app has to reload / restart to load plugins.

Any ideas ?

turbopasi
  • 3,327
  • 2
  • 16
  • 43

1 Answers1

11

After more and more research I stumbled over 2 packages :

both integrating npm to programmatically handle package installation at runtime. I settled for live-plugin-manager for now since its better documented and even allow package installation from local file system.

Pro

I was able to integrate the system out-of-the-box into a vanilla electron app. Works like a charm.

Cons

.I was not able to use it inside a vue electron boilerplate (like the one I said I was using in OP), since webpack is interferring with the require environment. But there sure is a solution to this.

Update : I was able to get it to work eventually inside a webpack bundled electron vue boilerplate. I accidentally mixed import and require . The following code works for me using live-plugin-manager

// plugin-loader.js
const path = require('path');
const { PluginManager } = require('live-plugin-manager');
const pluginInstallFolder = path.resolve(app.getPath('userData'), '.plugins');
const pluginManager = new PluginManager();

module.exports = async (pkg) => {
  // installs pkg from npm
  await pluginManager.install(pkg);
  const package = pluginManager.require(pkg);
  return package
}
// main.js
const pluginLoader = require('./plugin-loader');
pluginLoader("moment").then((moment) => {
   console.log(moment().format());
})

This will install "moment" package from npm during runtime into a local directory and load it into the app, without bundling it into the executable files.

turbopasi
  • 3,327
  • 2
  • 16
  • 43