基於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 支持下可以在頁面中和操作系統進行一些低級別的交互。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM