桌面端框架Electron使用问题整理和总结

1067次阅读  |  发布于4年以前

文章主要记录了使用electron日常开发中所遇到的一些坑以及怎样填坑,帮助其他开发的小伙伴少踩一些坑。

electron这个框架我就不过多介绍了,是使用nodeChromium架构的一个桌面端框架,如果有了解使用web技术开发桌面端,这个框架多少会听说过或者正在使用。

下面就记录一下自己在阅读文档的一些疑问以及开发过程中踩过的坑!

electron?

  1. SpectronDevtron 的作用?

2.<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />的作用?

3.electron-forge的作用?

4.在electron中使用iframewebview的的区别?

5.window.open()使用native和chrome的区别是什么?

6.electron-packagerelectron-builder 的打包区别?为什么推荐使用 electron-builder

7.在electron中使用node原生模块的时候,electron-rebuild能够简化原生的重编译?

electron进程之间通讯

1.主进程向渲染进程通讯

2.渲染进程向主进程通信

3.渲染进程向渲染进程通信

由于公司使用的技术栈是vue,所以需要将electronvue结合起来,当然结合的方式也不麻烦,这里我们选用了electron-vue这个开源框架。它已经将两者结合起来,并且能够独立打包成web,但在使用过程中还是有些疑问和坑的,记录一下

electron-vue 的坑与填坑?

  1. 这个框架使用vue-electron模块,它的作用是什么?
const electron = require('electron')

module.exports = {
  install: function (Vue) {
    Object.defineProperties(Vue.prototype, {
      $electron: {
        get () {
          return electron
        },
      },
    })
  },
}

2.这个框架使用vuex-electron模块,它的作用是什么?

3.在主进程中使用__dirname__filename 打包后,并不能得到我们预期的路径?

4.初始化完成项目后会报一个错误:ReferenceError: process is not defined

new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve(__dirname, '../src/index.ejs'),
+      templateParameters(compilation, assets, options) {
+        return {
+         compilation: compilation,
+         webpack: compilation.getStats().toJson(),
+          webpackConfig: compilation.options,
+          htmlWebpackPlugin: {
+            files: assets,
+            options: options
+          },
+          process,
+        };
+      },
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true,
        removeComments: true
      },
      nodeModules: process.env.NODE_ENV !== 'production'
        ? path.resolve(__dirname, '../node_modules')
        : false
    }),

5.构建完项目后electron版本默认是2.x, 升级版本后会报错module is not defined

mainWindow = new BrowserWindow({
  height: 563,
  useContentSize: true,
  width: 1000,
+  webPreferences: {
+    nodeIntegration: true
+  }
})

6.报错 Unable to install vue-devtools

7.在该项目中调用vuexmutations时,会报错Please, don't use direct commit's, use dispatch instead of this.

8.在vuex中存储的数据,即使刷新和重启项目,该数据依然存在(这里功能可以设置用户长期存储的数据)

9.使用npm run build:web打包时候,报错Error: Can't resolve 'fs' in xxxx

import Vue from 'vue'
import Vuex from 'vuex'
- import { createPersistedState, createSharedMutations } from 'vuex-electron'
import modules from './modules'

Vue.use(Vuex)

export default new Vuex.Store({
  modules,
+  plugins: process.env.IS_WEB ? [] : [
+    require('vuex-electron').createPersistedState(),
+    require('vuex-electron').createSharedMutations()
  ],
  strict: process.env.NODE_ENV !== 'production'
})

10.打包报错

electron调用native方法

安装环境(mac环境无需安装第1步)

  1. 管理员权限执行npm install --global windows-build-tools 安装python和C++环境 如果无法安装可以单独安装

2.npm install -g node-gyp 编译原生node模块(electron使用node原生模块需要编译) 3.node-gyp list 查看是否缺少node.lib 库,并按照提示安装 node-gyp install 4.在src/main/index.js中启用渲染层node集成

通过 node-ffi 模块调用C/C++ dll

  1. npm install ffi-napi --save 安装调用C/C++ dll的模块

2.npm install electron-rebuild ---save-dev 安装自动编译原生node模块

3.如果自动编译的话执行npx electron-rebuild,上步手动编译则不需要这一步了 4.剩下的就是在主进程里面调用native方法即可,渲染进程调用通过ipcRendereripcMain通信调用即可,举个小例子

// 主进程
// 调用示例
const ffi = require('ffi-napi')
const CTEST =  ffi.Library('dll文件路径', {
  // 文件内的方法和参数类型
  'Add': ['float', ['float', 'float']],
  'Hello': ['string', []],
  'StrLength': ['int', ['string']]
})
// 同步调用
CTEST.Hello()

// 异步调用
CTEST.StrLength.async('1234', (error, res) => {
  console.log(error, res)
})

这里有两点需要注意一下

 "extraFiles": [
    {
    "from": "",
    "to": ""
    }
]

通过 electron-edge-js 模块调用C# dll

  1. npm install electron-edge-js --save 安装调用C# dll的模块
  2. 这里electron的版本不能为8.x,版本7.x的页面刷新有bug,目前这个模块支持情况
 * Electron 1.6.x - Node.js v7.4.0.
* Electron 1.7.x - Node.js v7.9.0.
* Electron 1.8.x - Node.js v8.2.1.
* Electron 2.x - Node.js v8.9.3.
* Electron 3.x - Node.js v10.2.0.
* Electron 4.0.4+ - Node.js v10.11.0.
* Electron 5.x - Node.js v12.0.0.
* Electron 6.x - Node.js v12.4.0.
* Electron 7.x - Node.js v12.8.1
// 主进程
// 调用示例

const edge = require('electron-edge-js')
const edgeDll = edge.func({
  assemblyFile: 'dll文件路径',
  typeName: "Edge_test.Class1",
  methodName: "Concat"
})

edgeDll({ first: 'aaa', second: 'bb' }, function (error, result) {
  if (error) throw error
  console.log('C# DLL:',result)
})

通过robotjs控制鼠标键盘、node-serialport进行串口通讯等

  1. 使用方法这里不再赘述,文档查询即可。这些模块也是node原生模块,因此需要编译
  2. 自动编译同上npx electron-build,有时候自动编译不好使,就需要手动编译
  3. 手动编译 npm rebuild --runtime=electron --disturl=https://atom.io/download/atom-shell --target=<electron版本> --abi=<对应node版本的abi>或者直接进入模块文件夹中通过node-gyp编译:node-gyp rebuild
  4. abi查询网址:https://github.com/mapbox/node-pre-gyp/blob/master/lib/util/abi_crosswalk.json

自动更新

由于项目代码是放在自己服务并且不会进行签名,所以放弃electron内置的自动更新。项目使用的打包方式是electron-builder,最终决定使用electron-updater模块进行自动更新,它不依赖任何服务器并且可以从S3, GitHub或者任何其它静态文件存储更新,避开了 Electron 内置的更新机制

mac上代码必须要进行签名

这里给个简版示例

  1. npm install electron-updater --save 安装自动更新模块 2.主进程中写入更新代码
// 每次开启应用时候会去自动到文件服务器检查是否有更新,并自动更新重启
import { autoUpdater } from 'electron-updater'

autoUpdater.on('update-downloaded', () => {
  autoUpdater.quitAndInstall()
})

app.on('ready', () => {
  if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates()
})

3.配置打包更新服务器地址(这里配置从自己文件服务器获取更新)

"build": {
  "publish": {
    "provider": "generic",
    "url": "http://127.0.0.1:8080" // 服务器地址
  }
}

4.打包后安装,如果需要更新修改package.json的版本,重新打包,将.exe``latest.yml``.exe.blockmap 3个文件直接扔在文件服务器地址即可。下次用户打开应用便会自动更新

在electron中起个node服务

以上就是个人在阅读文档以及项目中遇到的部分问题和坑,记录分享一下,帮助其他小伙伴少走一些坑,感谢阅读!

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8