github地址
本地安裝環境准備
- 安裝node: * https://nodejs.org/en/download/
- 配置webpack: npm install -g webpack(sudo權限)
- windows配置cnpm:
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.scss
,common.scss
會去@import iconfont.css
(字體樣式),這時候iconfont.css
的字體路徑就會出現問題,webpack一直提示找不到依賴路徑。在開發環境下,我是將iconfont.cn獲取的字體文件遠程地址寫進build/index.html,這樣解決了問題。正式環境下,可以將字體文件代碼引入到App.vue文件中去
功能列表
- [ ] mac安裝包生成
- [ ] 新增各個模塊功能
- [x] windows安裝包生成 -- 完成
- [x] 應用自動更新 -- 完成
- [x] 中英文切換 -- 完成
- [x] 全局快捷鍵綁定 -- 完成
- [x] 即時通訊功能 -- 完成
- [x] excel表格導入導出 -- 完成
- [x] 登錄功能 -- 完成
- [x] mock.easy提供數據 -- 完成
development:
$ npm run dev
# express開啟服務,可以通過`http://localhost:port`訪問(熱重載)
# 原理:通過electron創建主體窗口,`mainWindow.loadURL(http://localhost:port)`,加載應用的 index.html
$ npm run app
# 運行`electron ./`,生成桌面應用
socket.io:
$ 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
),這樣之后,便可以使用mongod
、mongo
命令了,執行mongod
命令,一般會報錯,默認存儲文檔的目錄沒有,那可以這樣,新建一個文件夾,用來存儲mongo產生的文檔對象,執行mongod --dbpath D:\mongodb\db
,至於mongo(models/sechemas)、socket.io、express如何搭配去實現即時通訊的的功能,具體可以看代碼如何實現,對於這些新的東西,也只是了解個大概,后面准備花些時間去深入學習。
production:
$ npm run build
#生成正式文件到app/dist目錄(eletron應用目錄)
package:
$ npm run package:mac
$ npm run package:win
$ npm run package:linux
$ npm run package
將上一步`npm run build`后生成的正式文件,進行打包,生成程序,打包至`./package`目錄中
setup:
$ npm run setup
這里生成安裝包(僅適合於window),將上一步生成的package,通過grunt和grunt-electron-installer完成打包,打包至`./package_dir`
生成安裝包的過程:
- npm run build
- npm run package:win(目前只支持window)
- npm run setup
對於打包工具,這里使用的是electron-packager
,安裝命令:
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)\"
參數:
.
=> 應用目錄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
=> 忽略打包的目錄
詳細可看這里
打包成安裝程序,需要使用到grunt
、grunt-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
,點擊運行,進入一個安裝的過程,會有安裝的小動畫,如下圖:
而我們需要的是安裝完后自動生成快捷方式,這里使用的electron-squirrel-startup
npm包,然后在主線程文件中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的。
lint:
$ npm run lint
# lint項目(配置規則:.eslintrc)
上面的npm run script命令可能有些多,涉及的內容也比較多,文章后面會一一講解!下面上一波效果圖:
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!!!!
參考資料:
https://segmentfault.com/a/1190000008287730
https://segmentfault.com/a/1190000007616641
https://juejin.im/entry/5805e39ad20309006854e58f
https://github.com/hua1995116/webchat