vue+electron开发踩坑记录

Posted feiniao8651

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue+electron开发踩坑记录相关的知识,希望对你有一定的参考价值。

文章目录

背景

最近由于项目上的要求,需要开发一个基于数据展示页面。同时保证数据访问有可控性和安全性,需要对设备进行验证,保证非认证设备不会访问到数据。

框架选型

因为要有设备验证,所以选做PC端或者移动端。因为我们已有的数据接口,提供的都是大表格的数据,移动端开发的话,对数据结构还需要二次筛选处理,确定做PC端开发。
因为我们还有图表展示的需求,最先想到的就是echarts,也就是要用前端框架。
目前主流前端框架中,vue算是最容易上手的框架,非常适合我这种缺乏web前端开发经验的人。而且可以通过electron封装成pc客户端。所以最终的框架定为electron+vue+echarts。

开发过程

由于这方面网上教程非常多,我当时也是照着一个网上的实例来做的。实例操作很详细,但是后面整个系统开发快要结束了,才发现这里面有个坑,后面详细说。
大家在找教程的时候,注意的一点就是一定要用vue-cli3以上。

踩坑记录

问题1 vue-cli2无法使用vue cli plugin electron builder

上面说到,这里实例用的是vue-cli2来做的,所以生成的vue项目框架都是vue-cli2的,但是我们现在主流的都是vue-cli3或者vue-cli4了,我没用过vue,所以对vue-cli的版本也没有概念,当时就是看这个实例能运行,所以就照着做了。
最后要实现electron的ipcMain和ipcRenderer通信的时候,发现怎么配置都实现不了。查资料的过程中,发现很多教程中都是用到了vue cli plugin electron builder。尝试去使用这个包,发现要求vue-cli3以上。好在vue-cli的版本升级比较简单,而且升级之后的目录结构更加简单。
不过后来反思,配置实现不了通信,是因为很多配置教程都是要写在vue.config.js里的, 这是vue-cli3创建的项目里使用的配置文件。

问题2 vue component调用ipcRenderer

由于electron的渲染进程是在一个浏览器环境中运行,所以无法调用node的包,如果在vue component中调用node包,就会报错,类似fs.existsSync is not a function之类。
解决方案有几种,网上讨论最多的方式是使用preload,相当于预加载node的包,这样就能在渲染进程里调用了,在vue cli plugin electron builder官网上有写具体代码实现:

Preload files allow you to execute JS with Node integration in the context of your Vue App (shared window variable). Create a preload file and update your vue.config.js as so:

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

Then, update the new BrowserWindow call in your main process file (src/background.(js|ts) by default) to include the preload option:


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')
  
)

You will need to rerun electron:serve for the changes to take effect.

preload.js

import  ipcRenderer  from 'electron';
window.ipcRenderer = ipcRenderer;
console.log('preload');
console.log(window);

完成以上配置之后,按理来说在vue component中就能直接调用window.ipcRenderer了。
Index.vue

.....
mounted() 
    console.log('component');
    console.log(window);
    console.log(window.ipcRenderer);

......

注意!!!

我按照以上的教程配置之后,在component中调用window.ipcRenderer,却仍然是undefined,通过打印日志,在preload.js中的window是global对象,而在component中打印出来的window确是Window对象。

后来在stackoverflow中找到解决方法

It seems that in the current version of electron contextIsolation defaults to true, which makes the window that preload.js sees different from the one your vue app sees.

查看electron官网说明

上下文隔离功能将确保您的 预加载脚本 和 Electron的内部逻辑 运行在所加载的 webcontent网页 之外的另一个独立的上下文环境里。 这对安全性很重要,因为它有助于阻止网站访问 Electron 的内部组件 和 您的预加载脚本可访问的高等级权限的API 。
这意味着,实际上,您的预加载脚本访问的 window 对象并不是网站所能访问的对象。 例如,如果您在预加载脚本中设置 window.hello = 'wave ’ 并且启用了上下文隔离,当网站尝试访问window.hello对象时将得到未定义(undefined)。
每个应用程序都应该启用上下文隔离,Electron 12版本之后将默认启用它。

也就是说,从electron12 版本之后,默认打开了上下文隔离,所以在component中访问的window和preload.js里的window就不是同一个对象了。
所以要能引用到preload.js里的window,解决方式也很简单,直接上代码

const mainwindow = new BrowserWindow(format@@
  webPreference: 
  ......
    contextIsolation: false   //将contextIsolation设置为false即可
  
)

补充:vue-cli2和vue-cli3/4的一些区别

引用自Vue 项目从 Vue CLI 2 升级到 Vue CLI 4

  • Vue CLI 3 之后,官方开始推荐 零配置搭建项目 ,就像 Java 的 SpringBoot 一样
  • 在 Vue CLI 2 时代,Vue 的项目配置被分散在项目的 /build/ 和 /config/ 目录中
  • 然而从 Vue CLI 3 开始,所有的配置都被集成到了 vue.config.js 这一个文件中,并且这个文件默认是不被创建的

参考资料

Vue CLI Plugin Electron Builder
How to import ipcRenderer in vue.js ? __dirname is not defined
上下文隔离
Vue 项目从 Vue CLI 2 升级到 Vue CLI 4
vue脚手架vuecli2升级vuecli4及vue多页面配置

提供两个教程作为参考,我没有按照教程用,但是感觉作者写的蛮详细的
使用vue-cli-plugin-electron-builder开发vue-cli3.0+Electron桌面开发应用
手把手教你使用Electron5+vue-cli3开发跨平台桌面应用

以上是关于vue+electron开发踩坑记录的主要内容,如果未能解决你的问题,请参考以下文章

vue+ts+electron踩坑记录

electron-vue项目打包踩坑记录

Electron踩坑记录

electron-vue项目

Electron 踩坑记录- require is not defined

vue3 electron 记录