简体   繁体   中英

How to use electron to load the vue plugins installed dynamically into a plugins folder

I am using vue with electron to build a desktop application. I am using vue plugins to extend the functionality of the application. These vue plugins are hosted as npm modules in npm directory which can be installed from the applications plugin store using the live-plugin-manager which can be used to dynamically install plugins into plugins directory.

I am using webpack to compile the vue front-end. When I directly use these plugins, they work perfectly. I need to know if there is any way I can load these plugins dynamically from the folder each time application launches.

I have built the functionalities to install and uninstall the plugins. But I am unable to require these modules into the vue app. I tried using electron's remote.require call to fetch the module and using a loop called Vue.use() with the loaded plugin. But I keep on getting error.

    // loading plugins
    const plugs = await plugins.load()

    console.log(plugs)

    plugs.forEach(plug => {

        console.log(plug.install)

        Vue.use(plug)

    })

    // the plugins.load
    const remote = window.require('electron').remote

    if (remote) {
        const packager = remote.require('./package').default

        return packager.requireEnabled()
    }

    // the packager.requireEnabled() will load the enabled plugins 

This error shows up every time I use the above code.

Uncaught (in promise) Error: Could not call remote function 'install'. Check that the function signature is correct. Underlying error: Vue.use is not a function
    at callFunction (C:\Arjun\Tracing Paper Designs\works\Infolks\Tool\infolks-tool\node_modules\electron\dist\resources\electron.asar\browser\rpc-server.js:260:17)
    at C:\Arjun\Tracing Paper Designs\works\Infolks\Tool\infolks-tool\node_modules\electron\dist\resources\electron.asar\browser\rpc-server.js:411:10
    at EventEmitter.<anonymous> (C:\Arjun\Tracing Paper Designs\works\Infolks\Tool\infolks-tool\node_modules\electron\dist\resources\electron.asar\browser\rpc-server.js:275:21)
    at EventEmitter.emit (events.js:194:13)
    at WebContents.<anonymous> (C:\Arjun\Tracing Paper Designs\works\Infolks\Tool\infolks-tool\node_modules\electron\dist\resources\electron.asar\browser\api\web-contents.js:418:21)
    at WebContents.emit (events.js:194:13)

I was able to solve the issue by dynamic bundling of the plugins using browserify . I cannot share the entire code, but I will share the method I used.

  • First of all I included browserify into the dependency so that electron will include it in node_modules folder.
  • Then I set asar as false while packaging so that we can write into the app js file after bundling.
  • Each time the app starts it creates a js plugin loading script like:
const imports = []
const pluginUses = []

this.enabled.forEach((plugin, i) => {

    imports.push(`const plugin${i} = require("./modules/${plugin.name}");`)
    pluginUses.push(`Vue.use(plugin${i});`)

})

return `
    ${imports.join('\n')}

    window.BootstrapPlugin = {
        install(Vue, opts) {

            ${pluginUses.join('\n')}
        }
    }
`
  • each plugin are saved into plugins/modules folder. The dependencies are also installed into the folder automatically while installing.
  • The this.enabled is a getter that fetch all enabled plugins. plugin.name gets the package name of the plugin.
  • Once this script is created the program will write it into plugins/index.js using fs .
  • I have a bundle function which is called on app launch
const browserify = require('browserify')
const fs = require('fs')
const path = require('path')

// ...
function bundle() {
    const b = browserify({
        entries: [path.join(app.getAppPath(), 'plugins/index.js')],
        paths: [path.join(app.getAppPath(), 'plugins/modules'), path.join(app.getAppPath(), 'node_modules')]
    })

    const stream = fs.createWriteStream(path.join(app.getAppPath(), 'dist/packages.js'))

    b.bundle().pipe(stream)
}
  • Now I added the script dist/packages.js into the html file before the main js file (in my case dist/app.js).

  • Now I have a plugin BootstrapPlugin available globally that installs all the other plugins

  • All I have to do now is to use this plugin in the main.js file (dist/app.js)

Vue.use(window.BootstrapPlugin)

const app = new Vue({...})

Hope it helps someone :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM