How to import ipcRenderer in vue.js ? __dirname is not defined

Updated Answer – Nodeintegration disabled and contextIsolation enabled

In order to use the ipcRenderer with Vue CLI plugin Electron Builder you need to first setup electron to utilize a preload.js file.

Inside your vue.config.js file you need to add the preload.js path like this:

// vue.config.js - project root

module.exports = {
  pluginOptions: {
    electronBuilder: {
      preload: 'src/preload.js',
      // Or, for multiple preload files:
      preload: { preload: 'src/preload.js', otherPreload: 'src/preload2.js' }
    }
  }
}

Next you need to updated your background.js file to use preload.js in the web preferences like this:

// src/background.js

const win = new BrowserWindow({
  width: 800,
  height: 600,
  webPreferences: {
    // Use pluginOptions.nodeIntegration, leave this alone
    // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
    nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
    contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
    enableRemoteModule: true,
    preload: path.join(__dirname, 'preload.js'),
  },
})

Note: nodeIntegration is disabled and contextIsolation is enabled by default

Once you have that complete you can create the preload.js file in your src directory.
With contextIsolation enabled you need to import the contextBridge along with ipcRenderer. Then you can can expose the ipcRenderer to your client.

Then add this to the file:

// src/preload.js

import { contextBridge, ipcRenderer } from 'electron'

// Expose ipcRenderer to the client
contextBridge.exposeInMainWorld('ipcRenderer', {
  send: (channel, data) => {
    let validChannels = ['nameOfClientChannel'] // <-- Array of all ipcRenderer Channels used in the client
    if (validChannels.includes(channel)) {
      ipcRenderer.send(channel, data)
    }
  },
  receive: (channel, func) => {
    let validChannels = ['nameOfElectronChannel'] // <-- Array of all ipcMain Channels used in the electron
    if (validChannels.includes(channel)) {
      // Deliberately strip event as it includes `sender`
      ipcRenderer.on(channel, (event, ...args) => func(...args))
    }
  }
})

Note: You need to make sure your preload.js file is in the src folder and not dist_electron

To test and make sure the preload file is working you can also create an alert in the preload.js file

// src/preload.js

import { contextBridge, ipcRenderer } from 'electron'

// Expose ipcRenderer to the client
contextBridge.exposeInMainWorld('ipcRenderer', {
  send: (channel, data) => {
    let validChannels = ['nameOfClientChannel'] // <-- Array of all ipcRenderer Channels used in the client
    if (validChannels.includes(channel)) {
      ipcRenderer.send(channel, data)
    }
  },
  receive: (channel, func) => {
    let validChannels = ['nameOfElectronChannel'] // <-- Array of all ipcMain Channels used in the electron
    if (validChannels.includes(channel)) {
      // Deliberately strip event as it includes `sender`
      ipcRenderer.on(channel, (event, ...args) => func(...args))
    }
  }
})

alert("It Worked!") // Remove this line once you confirm it worked

When you have verified that your preload script is working correctly, you can access the ipcRenderer from your vue app.

like this:

// src/App.vue

<template>
     \\ Some html
</template>

<script>
  export default {
    name: "App",
    methods: {
      test(){
        window.ipcRenderer.send(channel, args...) // or any other ipcRenderer method you want to invoke
    }
};
</script>

In electron you can listen for those events

// background.js
ipcMain.on(channel, (event, args) => {
  // Do stuff
});

Sources:

Original Answer

In order to use the ipcRenderer with Vue CLI plugin Electron Builder you need to first setup electron to utilize a preload.js file.

Inside your vue.config.js file you need to add the preload.js path like this:

// vue.config.js - project root

module.exports = {
  pluginOptions: {
    electronBuilder: {
      preload: 'src/preload.js',
      // Or, for multiple preload files:
      preload: { preload: 'src/preload.js', otherPreload: 'src/preload2.js' }
    }
  }
}

Next you need to updated your background.js file to use preload.js in the web preferences like this:

// src/background.js

const win = new BrowserWindow({
  width: 800,
  height: 600,
  webPreferences: {
    // Use pluginOptions.nodeIntegration, leave this alone
    // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/configuration.html#node-integration for more info
    nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
+   preload: path.join(__dirname, 'preload.js')
  }
})

Once you have that complete you can create the preload.js file in your src directory

Then add this to the file:

// src/preload.js

import { ipcRenderer } from 'electron'
window.ipcRenderer = ipcRenderer

Note: You need to make sure your preload.js file is in the src folder and not dist_electron

To test and make sure the preload file is working you can also create an alert in the preload.js file

// src/preload.js

import { ipcRenderer } from 'electron'
window.ipcRenderer = ipcRenderer

alert("It Worked!") // Remove this line once you confirm it worked

When you have verified that your preload script is working correctly, you can access the ipcRenderer from your vue app.

like this:

// src/App.vue

<template>
     \\ Some html
</template>

<script>
  export default {
    name: "App",
    methods: {
      test(){
        window.ipcRenderer.send(channel, args...) // or any other ipcRenderer method you want to invoke
    }
};
</script>

Sources:

Leave a Comment