electron + vue 實踐項目

github地址

本地安裝環境準備

npm install -g cnpm --registry=https://registry.npm.taobao.org
    由於npm的默認倉庫在國外,下載很慢,國內淘寶搞了個CNPM,每10分鐘同步一次,徹底夠用了
  • 固然也可使用yarn下載
npm install -g yarn
    yarn install

依賴包安裝

  • 進入項目目錄
  • 執行cnpm install

安裝問題

  • cnpm install以後,可能會因爲網絡很差而致使一些包安裝不完整,這裏推薦使用yarn進行安裝
  • 須要額外安裝vue-style-loader、vue-template-compiler,否則vue-loader會報錯
  • electron配置項(config.js)爲true時,運行npm run dev,瀏覽器訪問會報錯, Uncaught ReferenceError: require is not defined,緣由能夠去這裏看,因爲配置config.electron是開啓狀態,因而require被browserified化了,不是原先node原生require函數,因此在browser會出現此問題
  • 應用打包的時候,須要注意package.json的main配置項main,必須指向electron的主線程文件,此處爲app/index.js

字體引入問題

對於webpack對於引入字體文件一直都會有問題,有時候你使用了file-laoder,url-loader,可是在使用仍是會存在一些問題,好比渲染進程入口文件components/App.vue但願引入common.scsscommon.scss會去@import iconfont.css(字體樣式),這時候iconfont.css的字體路徑就會出現問題,webpack一直提示找不到依賴路徑。在開發環境下,我是將iconfont.cn獲取的字體文件遠程地址寫進build/index.html,這樣解決了問題。正式環境下,能夠將字體文件代碼引入到App.vue文件中去css

功能列表

  • [ ] mac安裝包生成
  • [ ] 新增各個模塊功能
  • [x] windows安裝包生成 -- 完成
  • [x] 應用自動更新 -- 完成
  • [x] 中英文切換 -- 完成
  • [x] 全局快捷鍵綁定 -- 完成
  • [x] 即時通信功能 -- 完成
  • [x] excel表格導入導出 -- 完成
  • [x] 登陸功能 -- 完成
  • [x] mock.easy提供數據 -- 完成

development:html

$ npm run dev
# express開啓服務,能夠經過`http://localhost:port`訪問(熱重載)
# 原理:經過electron建立主體窗口,`mainWindow.loadURL(http://localhost:port)`,加載應用的 index.html

$ npm run app
# 運行`electron ./`,生成桌面應用

socket.io:vue

$ npm run socket

使用express + mongoDB + socket.io引入基於node的即時通信模塊

本地調試時,只需運行npm run dev => npm run app,須要開啓即時通信的功能的須要npm run sock,這裏須要注意即時通信模塊目前沒有遷移至服務器,要在本地運行,須要使用express起一個服務(./socket/),這裏的數據庫集成使用的是mongoDB,因此必需要安裝mongoDB,而後配置環境變量(好比說我安裝的目錄是d:,個人環境變量這樣配置,D:\Program Files\MongoDB\Server\3.4\bin),這樣以後,即可以使用mongodmongo命令了,執行mongod命令,通常會報錯,默認存儲文檔的目錄沒有,那能夠這樣,新建一個文件夾,用來存儲mongo產生的文檔對象,執行mongod --dbpath D:\mongodb\db,至於mongo(models/sechemas)、socket.io、express如何搭配去實現即時通信的的功能,具體能夠看代碼如何實現,對於這些新的東西,也只是瞭解個大概,後面準備花些時間去深刻學習。node

production:linux

$ npm run build
#生成正式文件到app/dist目錄(eletron應用目錄)

package:webpack

$ npm run package:mac
$ npm run package:win
$ npm run package:linux
$ npm run package

將上一步`npm run build`後生成的正式文件,進行打包,生成程序,打包至`./package`目錄中

img

setup:git

$ npm run setup

這裏生成安裝包(僅適合於window),將上一步生成的package,經過grunt和grunt-electron-installer完成打包,打包至`./package_dir`

img

生成安裝包的過程:github

  • npm run build
  • npm run package:win(目前只支持window)
  • npm run setup

對於打包工具,這裏使用的是electron-packager,安裝命令:web

rimraf package && electron-packager . TEST --platform=win32 --arch=x64 --overwrite --icon=hosts.ico --out=./package --electron-version=1.6.11 --version-string.CompanyName=TEST --version-string.ProductName=TEST --ignore=\"(build|client$|static|theme|.gitignore|LICENSE|README.md|.editorconfig|.eslintrc|node_modules|gruntPackage.json|Gruntfile.js|yarn.lock|socket|package_dir|git_img)\"

參數:mongodb

  • . => 應用目錄
  • TEST => 應用名稱
  • --platform=win32 => 要打包的平臺
  • --overwrite => 覆蓋模式安裝
  • --icon=hosts.ico => 應用圖標(window時能夠是.ico.png,mac時能夠爲.icns
  • --out=./package => 輸出目錄
  • --electron-version => electron版本
  • --version-string.CompanyName=TEST --version-string.ProductName=TEST => 爲了生成安裝包的時候,應用名字爲TEST,而不是默認的electron
  • --ignore=XXX => 忽略打包的目錄

詳細可看這裏

打包成安裝程序,須要使用到gruntgrunt-electron-installer,請保證事先安裝好
package.json設置:

{
    "version": "1.0.0", // 這個是必須的,爲了後面使用electron updater實現自動更新
    "productName": "my-electron",
    "description": "My Superb Vue Project For Electron",
    ......
}

Gruntfile.js文件以下詳細

var grunt = require('grunt')

// 配置
grunt.config.init({
    pkg: grunt.file.readJSON('package.json'), // 這裏會去獲取版本號
    'create-windows-installer': {
        x64: {
            authors: 'xiaobinwu <xiaobin_wu@yahoo.com>', // 做者
            projectUrl: '',
            appDirectory: './package/TEST-win32-x64', // 要打包的輸入目錄
            outputDirectory: './package_dir', // grunt打包後的輸出目錄
            exe: 'TEST.exe', // 生成的exe文件
            description: 'My Superb Vue Project For Electron',
            setupIcon: './app/hots.ico', // 圖標
            noMsi: true // 是否生成.msi
        }
    }
})

// 加載任務
grunt.loadNpmTasks('grunt-electron-installer')

// 設置爲默認
grunt.registerTask('default', ['create-windows-installer'])

因而就會生成如上圖所示的my-electronSetup.exe,點擊運行,進入一個安裝的過程,會有安裝的小動畫,以下圖:
gif
而咱們須要的是安裝完後自動生成快捷方式,這裏使用的electron-squirrel-startupnpm包,而後在主線程文件中app/index.js中寫入startupEventHandle方法,安裝時觸發squirrel.window的一些命令,將其放在建立主體窗口的回調函數中,代碼以下:

app.on('ready', function(){
    ......
    startupEventHandle()
    ......
})
......

function startupEventHandle () {
    if (require('electron-squirrel-startup')) { return }
    // 安裝和更新時添加快捷方式,刪除和卸載時刪除快捷方式
    var handleStartupEvent = function () {
        if (process.platform !== 'win32') {
            return false
        }
        var squirrelCommand = process.argv[1]
        switch (squirrelCommand) {
            case '--squirrel-install':
            case '--squirrel-updated':
                install()
                return true
            case '--squirrel-uninstall':
                uninstall()
                app.quit()
                return true
            case '--squirrel-obsolete':
                app.quit()
                return true
        }
        // 安裝
        function install () {
            var cp = require('child_process')
            var updateDotExe = path.resolve(path.dirname(process.execPath), '..', 'update.exe')
            var target = path.basename(process.execPath)
            var child = cp.spawn(updateDotExe, ['--createShortcut', target], { detached: true })
            child.on('close', function (code) {
                app.quit()
            })
        }
        // 卸載
        function uninstall () {
            var cp = require('child_process')
            var updateDotExe = path.resolve(path.dirname(process.execPath), '..', 'update.exe')
            var target = path.basename(process.execPath)
            var child = cp.spawn(updateDotExe, ['--removeShortcut', target], { detached: true })
            child.on('close', function (code) {
                app.quit()
            })
        }
    }
    if (handleStartupEvent()) {
        return
    }
}

這樣即可以在安裝時生成快捷方式,卸載時刪除快捷方式了,在這個過程當中,有可能回報electron-squirrel-startup module not found相似的錯誤,那是electron-packager打包時,過濾掉了node_moudles目錄,因此須要手動添加到生成的package裏面。至於網上的一些教程說,是須要安裝vs2015環境,而且將msbuild程序聲明成環境變量,可是我以爲應該是缺乏npm包的緣由,你們也能夠試試,我本地是原本就安裝過vs2015的,並且安裝包沒辦法自定義安裝目錄,默認都是安裝在C:\Users\Wushaobin\AppData\Local\XXX下面的。

lint:

$ npm run lint
# lint項目(配置規則:.eslintrc)
上面的npm run script命令可能有些多,涉及的內容也比較多,文章後面會一一講解!下面上一波效果圖:

gif
gif
gif
gif
gif

electron自動更新

前面咱們也有提到過自動更新,這裏使用的官方提供的electron.autoUpdater模塊去更新,坑爹的是官方對這一功能的描述真是少之又少,autoUpdater的一些方法和事件這裏能夠去了解清楚,autoUpdater.setFeedURL(url)這一方法是重中之重,url放着高版本的文件(.exe,.nupkg,RELEASES),這裏我是存儲在阿里oss,而後autoUpdater.checkForUpdates()會去檢查是否須要更新,它會觸發error、checking-for-update、update-available、update-downloaded中的一些事件,而咱們須要利用主進程跟渲染進程之間的通信(ipc/remote/webContent),來觸發更新,具體代碼以下:

function updateHandle () {
    ipcMain.on('check-for-update', function (event, arg) {
        if (process.platform !== 'win32') {
            return false
        }
        let appName = '門店系統'
        let appIcon = __dirname + '/hots.ico'
        let message = {
            error: '檢查更新出錯',
            checking: '正在檢查更新……',
            updateAva: '下載更新成功',
            updateNotAva: '如今使用的就是最新版本,不用更新',
            downloaded: '最新版本已下載,將在重啓程序後更新'
        }
        const os = require('os')
        const { dialog } = require('electron')
        // 放最新版本文件的文件夾的服務器地址
        // 阿里oss
        autoUpdater.setFeedURL('http://electron20170815.oss-cn-beijing.aliyuncs.com/electron/')
        autoUpdater.on('error', function (error) {
            return dialog.showMessageBox(mainWindow, {
                type: 'info',
                icon: appIcon,
                buttons: ['OK'],
                title: appName,
                message: message.error,
                detail: '\r' + error
            })
        })
        .on('checking-for-update', function (e) {
            return dialog.showMessageBox(mainWindow, {
                type: 'info',
                icon: appIcon,
                buttons: ['OK'],
                title: appName,
                message: message.checking
            })
        })
        .on('update-available', function (e) {
            var downloadConfirmation = dialog.showMessageBox(mainWindow, {
                type: 'info',
                icon: appIcon,
                buttons: ['OK'],
                title: appName,
                message: message.updateAva
            })
            if (downloadConfirmation === 0) {
                return
            }
        })
        .on('update-not-available', function (e) {
            return dialog.showMessageBox(mainWindow, {
                type: 'info',
                icon: appIcon,
                buttons: ['OK'],
                title: appName,
                message: message.updateNotAva
            })
        })
        .on('update-downloaded',  function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
            var index = dialog.showMessageBox(mainWindow, {
                type: 'info',
                icon: appIcon,
                buttons: ['如今重啓', '稍後重啓'],
                title: appName,
                message: message.downloaded,
                detail: releaseName + '\n\n' + releaseNotes
            })
            if (index === 1) { return }
            autoUpdater.quitAndInstall()
        })
        autoUpdater.checkForUpdates()
    })
}

若是內容對你有幫助的話,能夠去github給個star!!!!

參考資料:
http://www.javashuo.com/article/p-tqhzdxde-co.html
http://www.javashuo.com/article/p-zdjqrogk-dx.html
https://juejin.im/entry/5805e39ad20309006854e58f
https://github.com/hua1995116/webchat


Generated by VuePack.
vuePack Issue

相關文章
相關標籤/搜索