基于Electron搭建跨平台应用程序

TOC
https://www.electronjs.org/docs

搭建环境:
Mac 10.15.4
VS Code
网络FQ(不然非常慢)

什么是Electron?

Electron是一个创建原生应用程序的框架,基于Node.js和Chromium实现了通过JavaScript, HTML 和 CSS 等 Web 技术构建跨平台应用程序的能力。
其中,Electron还封装了一些功能,包括自动更新、原生的菜单和通知、崩溃报告、调试和性能分析等。

electron-vue脚手架

为了便于后续的开发,我们采用electron-vue脚手架基于vue搭建项目。
https://simulatedgreg.gitbooks.io/electron-vue/content/en/getting_started.html

包管理我们采用yarn,否则可能报出现一些奇怪的错误。
https://classic.yarnpkg.com/en/docs/install#mac-stable

#1、安装脚手架
sudo npm install -g vue-cli


#2、初始化项目,根据需要选择插件
vue init simulatedgreg/electron-vue test


? Target directory exists. Continue? Yes
? Application Name test
? Application Id com.leestar54.test
? Application Version 0.0.1
? Project description test
? Use Sass / Scss? Yes
? Select which Vue plugins to install axios, vue-electron, vue-router, vuex, vue
x-electron
? Use linting with ESLint? Yes
? Which ESLint config would you like to use? Standard
? Set up unit testing with Karma + Mocha? No
? Set up end-to-end testing with Spectron + Mocha? No
? What build tool would you like to use? builder
? author leestar54


   vue-cli · Generated "test".


#3、自动安装依赖
yarn
yarn install v1.19.2
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 0.06s.


4、运行测试
npm run dev

此时你会发现报错

ReferenceError: process is not defined

https://github.com/SimulatedGREG/electron-vue/issues/871
官方issue已有解决方案,但是一直未close,临时方案如下:
modify HtmlWebpackPlugin in .electron-vue/webpack.web.config.js and .electron-vue/webpack.renderer.config.js:

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
      },

再次执行npm run dev,成功。

引入iview组件库

安装

为了便于后续开发,引入iview作为UI组件库
https://www.iviewui.com/docs/introduce

yarn add view-design


success Saved 9 new dependencies.
info Direct dependencies
└─ view-design@4.2.0
info All dependencies
├─ async-validator@1.12.2
├─ batch-processor@1.0.0
├─ element-resize-detector@1.2.1
├─ js-calendar@1.2.3
├─ lodash.throttle@4.1.1
├─ popper.js@1.16.1
├─ tinycolor2@1.4.1
├─ v-click-outside-x@3.7.1
└─ view-design@4.2.0

main.js引入插件

基于iview官方示例代码,仅供参考

import Vue from 'vue'
import axios from 'axios'


import App from './App'
import router from './router'
import store from './store'
import ViewUI from 'view-design'
import 'view-design/dist/styles/iview.css'


Vue.use(ViewUI)


if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
Vue.http = Vue.prototype.$http = axios
Vue.config.productionTip = false


/* eslint-disable no-new */
new Vue({
  components: { App },
  router,
  store,
  template: '<App/>'
}).$mount('#app')

调整App.vue

<style scoped>
.layout {
  border: 1px solid #d7dde4;
  background: #f5f7f9;
  position: relative;
  border-radius: 4px;
  overflow: hidden;
}
.layout-logo {
  width: 100px;
  height: 30px;
  background: #5b6270;
  border-radius: 3px;
  float: left;
  position: relative;
  top: 15px;
  color: white;
  text-align: center;
  line-height: 28px;
}
.layout-nav {
  width: 420px;
  margin: 0 auto;
  margin-right: 20px;
}
</style>
<template>
  <div id="app">
    <div class="layout">
      <Layout :style="{ minHeight: '100vh' }">
        <Header>
          <Menu mode="horizontal" theme="dark" active-name="1">
            <div class="layout-logo">test</div>
            <div class="layout-nav">
              <MenuItem name="1">
                <Icon type="ios-navigate"></Icon>
                Item 1
              </MenuItem>
              <MenuItem name="2">
                <Icon type="ios-keypad"></Icon>
                Item 2
              </MenuItem>
              <MenuItem name="3">
                <Icon type="ios-analytics"></Icon>
                Item 3
              </MenuItem>
              <MenuItem name="4">
                <Icon type="ios-paper"></Icon>
                Item 4
              </MenuItem>
            </div>
          </Menu>
        </Header>
        <Layout>
          <Sider hide-trigger :style="{ background: '#fff' }">
            <Menu active-name="1-2" theme="light" width="auto" :open-names="['1']">
              <MenuItem name="1-1">
                <Icon type="ios-paper" />
                Menu 1
              </MenuItem>
              <Submenu name="1">
                <template slot="title">
                  <Icon type="ios-navigate"></Icon>
                  Item 1
                </template>
                <MenuItem name="1-1">Option 1</MenuItem>
                <MenuItem name="1-2">Option 2</MenuItem>
                <MenuItem name="1-3">Option 3</MenuItem>
              </Submenu>
              <Submenu name="2">
                <template slot="title">
                  <Icon type="ios-keypad"></Icon>
                  Item 2
                </template>
                <MenuItem name="2-1">Option 1</MenuItem>
                <MenuItem name="2-2">Option 2</MenuItem>
              </Submenu>
              <Submenu name="3">
                <template slot="title">
                  <Icon type="ios-analytics"></Icon>
                  Item 3
                </template>
                <MenuItem name="3-1">Option 1</MenuItem>
                <MenuItem name="3-2">Option 2</MenuItem>
              </Submenu>
            </Menu>
          </Sider>
          <Layout :style="{ padding: '24px' }">
            <Breadcrumb :style="{ margin: '24px 0' }">
              <BreadcrumbItem>Home</BreadcrumbItem>
              <BreadcrumbItem>Components</BreadcrumbItem>
              <BreadcrumbItem>Layout</BreadcrumbItem>
            </Breadcrumb>
            <Content
              :style="{
                padding: '24px',
                minHeight: '280px',
                background: '#fff',
                position: 'relative'
              }"
            >
              <router-view @showSpin="showSpin"></router-view>
              <Spin size="large" fix v-if="spinShow"></Spin>
            </Content>
          </Layout>
        </Layout>
      </Layout>
    </div>
  </div>
</template>


<script>
export default {
  data() {
    return {
      spinShow: false
    }
  },
  methods: {
    showSpin(isShow) {
      this.spinShow = isShow
    }
  }
}
</script>


<style>
/* CSS */
</style>


开始编写业务代码吧。

构建

https://www.electron.build/
Electron的构建基于electron-builder,它会根据指定的平台,加载相应的依赖。具体的构建参数见官方文档。
但对于系统和环境都有一定的要求,所以不要指望在一个系统一定能构建所有平台的应用。
默认情况下运行npm run build会直接构建本系统的应用。具体见package.json中的scripts项。

build报错Can't locate Mac/Memory.pm

需要将electron-builder 升级到最新版本

yarn add electron-builder 

MAC

"build": "node .electron-vue/build.js && electron-builder",

npm run build


 OKAY  take it away `electron-builder`


  • electron-builder  version=22.5.1 os=19.4.0
  • loaded configuration  file=package.json ("build" field)
  • writing effective config  file=build/builder-effective-config.yaml
  • packaging       platform=darwin arch=x64 electron=2.0.18 appOutDir=build/mac
  • skipped macOS application code signing  reason=cannot find valid "Developer ID Application" identity or custom non-Apple code signing certificate, see https://electron.build/code-signing allIdentities=
                                                1) 8206A06DA61D4CB03848E22BD5B3B09CC469E537 "localhost" (CSSMERR_TP_NOT_TRUSTED)
                                                2) 7E5D9BD7FBE6A425B0631D51532512F0AD85D01F "ExpressVPN Client" (CSSMERR_TP_NOT_TRUSTED)
                                                   2 identities found

                                                Valid identities only
                                                   0 valid identities found
  • building        target=macOS zip arch=x64 file=build/test-0.0.1-mac.zip
  • building        target=DMG arch=x64 file=build/test-0.0.1.dmg
  • building block map  blockMapFile=build/test-0.0.1.dmg.blockmap
  • building embedded block map  file=build/test-0.0.1-mac.zip

Windows

可以自动基于nsis生成安装包
"build:win": "node .electron-vue/build.js && electron-builder --win --x64",

npm run build:win
 OKAY  take it away `electron-builder`


  • electron-builder  version=22.5.1 os=19.4.0
  • loaded configuration  file=package.json ("build" field)
  • writing effective config  file=build/builder-effective-config.yaml
  • packaging       platform=win32 arch=x64 electron=2.0.18 appOutDir=build/win-unpacked
  • building        target=nsis file=build/test Setup 0.0.1.exe archs=x64 oneClick=true perMachine=false
  • downloading     url=https://github.com/electron-userland/electron-builder-binaries/releases/download/nsis-3.0.4.1/nsis-3.0.4.1.7z size=1.3 MB parts=1
  • downloaded      url=https://github.com/electron-userland/electron-builder-binaries/releases/download/nsis-3.0.4.1/nsis-3.0.4.1.7z duration=5.37s
  • building block map  blockMapFile=build/test Setup 0.0.1.exe.blockmap

Linux

注:linux构建需要完善package中的homepage,email参数
"build:linux": "node .electron-vue/build.js && electron-builder --linux --x64",
在build配置中linux的target设为AppImage

 OKAY  take it away `electron-builder`


  • electron-builder  version=22.5.1 os=19.4.0
  • loaded configuration  file=package.json ("build" field)
  • writing effective config  file=build/builder-effective-config.yaml
  • packaging       platform=linux arch=x64 electron=2.0.18 appOutDir=build/linux-unpacked
  • building        target=AppImage arch=x64 file=build/test-0.0.1.AppImage
  • application Linux category is set to default "Utility"  reason=linux.category is not set and cannot map from macOS docs=https://www.electron.build/configuration/linux

其他

调试时vue-devtools不起作用

需要FQ ,否则会一直提示超时,所以不显示面板,FQ之后自动下载,过会就有了。

Prettier不支持space-before-function-paren

https://github.com/prettier/prettier-vscode/issues/494
建议关闭eslint的space-before-function-paren监测

npm install时node-gyp出现错误

执行一下指令,必须已安装了Xcode
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

electron did not match expected checksum

删除项目文件夹下的node_modules
删除/Users/lixin下的.npm和.electron文件
重新install

主进程与渲染进程

主进程:通常是名为main.js 的文件,是每个 Electron 应用的入口文件。它控制着整个 App 的生命周期,从打开到关闭。 它也管理着系统原生元素比如菜单,菜单栏,Dock 栏,托盘等。 主进程负责创建 APP 的每个渲染进程。而且整个 Node API 都集成在里面。
每个 app 的主进程文件都定义在 package.json 中的 main 属性当中。这也是为什么 electron. 能够知道应该使用哪个文件来启动。
在Chromium中, 这个进程被称为 "浏览器进程"。它在Electron被重新命名, 以避免与渲染器进程混淆。

渲染进程:你的应用内的一个浏览器窗口。与主进程不同的是,它能够同时存在多个而且运行在不一样的进程。而且它们也能够被隐藏。
在通常的浏览器内,网页通常运行在一个沙盒的环境挡住并且不能够使用原生的资源。 然而 Electron 的用户在 Node.js 的 API 支持下可以在页面中和操作系统进行一些低级别的交互。

posted @ 2020-04-26 18:48  leestar54  阅读(2693)  评论(0编辑  收藏  举报