最近一直在學習 Electron 開發桌面應用程序,目的是想作一個桌面編輯器,雖然一直在使用Typore這款神器,但無奈Typore太過國際化,在國內水土不服,沒法知足個人一些需求。前端
好比實現本地圖片上傳到雲端(mac版能夠藉助iPic),沒法幫我把本地圖片和文章一塊兒發佈到博客園、CSDN、SegmentFault、掘金等國內知名博客平臺,要麼使用一些免費或付費的圖牀,藉助相似iPic的工具,把圖片一鍵上傳到雲端。node
我我的也嘗試過七牛雲的免費10G存儲空間,可是說實話,這些免費的空間到最後必定是爲了讓你成爲付費用戶,各類限制各類吐槽在網上很容易能夠搜索到。git
免費的圖牀如新浪微博等,還算是比較好的圖牀工具,相比一些網絡上的壓根不知道啥公司甚至是歸屬我的的免費圖牀,新浪應該是比較靠譜的,相對來講能夠保證圖片的存活時間,我我的用過一些免費的圖牀網站,記得印象深入的就是服務器出問題,網站掛個公告,曾經的圖片再去訪問就是默認的404。github
雖然新浪家大業大不是說倒閉就倒閉的,圖片相對穩定可靠,不過新浪的圖片服務器會檢測訪問來源Referer來防止外部網站引用,形成訪問403。web
總結起來就是一句話,圖片仍是隨着文章一鍵發佈到博客平臺比較好。要丟一塊兒丟~npm
緣起這個動機,可是下定決心依舊是困難重重。json
我我的是一個Java工程師,雖然說搞過Andorid、HTML前端,但對前端深感不適的我果斷放棄了。對於桌面程序開發,我連Swing都不會,造一個Markdown編輯器有點難,況且還要加上這些定製功能。api
猶猶豫豫,仍是決定去嘗試一下。因而調研寫跨平臺的一些途徑。瀏覽器
先嚐試Swing,不過Swing很差實現我指望的一些功能,改爲JavaFX卻是能夠,不過說實話,寫起來很累,太過繁瑣,就放棄了。最後把目光瞄向electron,就它了,HTML+Js+Css,聽起來就很簡單,事實證實,不管是測試仍是打包都很方便。服務器
決定以後,便開始進行 Electron 的系統學習。
第一步就是安裝 Electron 的本地開發環境,這也是大多數應用開發的第一步。
你須要安裝 Node.js 在你的本地電腦,Electron 也是依賴於 Node.js 的環境,嚴格來講, Electron 經過將 Chromium 和 Node.js 合併到同一個運行時環境中,並將其打包爲Mac,Windows和Linux系統下的應用來實現這一目的。
關於 Electron 的具體開發流程,這裏再也不贅述,你徹底能夠在開發中使用Web前端開發的思惟,除了在處理多個窗口之間交互的時候,就不得不瞭解Eelctron的進程機制。
Electron 運行 package.json 的 main 腳本的進程被稱爲主進程。 在主進程中運行的腳本經過建立web頁面來展現用戶界面。 一個 Electron 應用老是有且只有一個主進程。
因爲 Electron 使用了 Chromium 來展現 web 頁面,因此 Chromium 的多進程架構也被使用到。 每一個 Electron 中的 web 頁面運行在它本身的渲染進程中。
在普通的瀏覽器中,web頁面一般在沙盒環境中運行,而且沒法訪問操做系統的原生資源。 然而 Electron 的用戶在 Node.js 的 API 支持下能夠在頁面中和操做系統進行一些底層交互。
主進程使用 BrowserWindow 實例建立頁面。 每一個 BrowserWindow 實例都在本身的渲染進程裏運行頁面。 當一個 BrowserWindow 實例被銷燬後,相應的渲染進程也會被終止。
主進程管理全部的web頁面和它們對應的渲染進程。 每一個渲染進程都是獨立的,它只關心它所運行的 web 頁面。
在頁面中調用與 GUI 相關的原生 API 是不被容許的,由於在 web 頁面裏操做原生的 GUI 資源是很是危險的,並且容易形成資源泄露。 若是你想在 web 頁面裏使用 GUI 操做,其對應的渲染進程必須與主進程進行通信,請求主進程進行相關的 GUI 操做。
那麼進程間如何通信?
Electron爲主進程( main process)和渲染器進程(renderer processes)通訊提供了多種實現方式,如可使用ipcRenderer 和 ipcMain模塊發送消息,使用 remote模塊進行RPC方式通訊。
你還能夠用 Electron 內的 IPC 機制實現。將數據存在主進程的某個全局變量中,而後在多個渲染進程中使用 remote 模塊來訪問它。
示例代碼:
// 在主進程中 global.sharedObject = { someProperty: 'default value' }
// 在第一個頁面中 require('electron').remote.getGlobal('sharedObject').someProperty = 'new value'
// 在第二個頁面中 console.log(require('electron').remote.getGlobal('sharedObject').someProperty)
Electron在主進程和渲染進程中提供了大量API去幫助開發桌面應用程序, 在主進程和渲染進程中,你能夠經過require的方式將其包含在模塊中以此,獲取Electron的API
const electron = require('electron')
全部Electron的API都被指派給一種進程類型。 許多API只能被用於主進程或渲染進程中,但其中一些API能夠同時在上述兩種進程中使用。 每個API的文檔都將聲明你能夠在哪一種進程中使用該API。
Electron中的窗口是使用BrowserWindow類型建立的一個實例, 它只能在主進程中使用。
// 這樣寫在主進程會有用,可是在渲染進程中會提示'未定義' const { BrowserWindow } = require('electron') const win = new BrowserWindow()
由於進程之間的通訊是被容許的, 因此渲染進程能夠調用主進程來執行任務。 Electron經過remote模塊暴露一些一般只能在主進程中獲取到的API。 爲了在渲染進程中建立一個BrowserWindow的實例,一般使用remote模塊爲中間件:
// 這樣寫在渲染進程中時行得通的,可是在主進程中是'未定義' const { remote } = require('electron') const { BrowserWindow } = remote const win = new BrowserWindow()
Electron同時在主進程和渲染進程中對Node.js 暴露了全部的接口。 這裏有兩個重要的定義:
1)全部在Node.js可使用的API,在Electron中一樣可使用。 在Electron中調用以下代碼是有用的:
const fs = require('fs') const root = fs.readdirSync('/') // 這會打印出磁盤根級別的全部文件 // 同時包含'/'和'C:\'。 console.log(root)
2)你能夠在你的應用程序中使用Node.js的模塊。 選擇您最喜歡的 npm 模塊。 npm 提供了目前世界上最大的開源代碼庫,那裏包含良好的維護、通過測試的代碼,提供給服務器應用程序的特點功能也提供給Electron。
例如,在你的應用程序中要使用官方的AWS SDK,你須要首先安裝它的依賴:
npm install --save aws-sdk
而後在你的Electron應用中,經過require引入並使用該模塊,就像構建Node.js應用程序那樣:
// 準備好被使用的S3 client模塊 const S3 = require('aws-sdk/clients/s3')
有一個很是重要的提示: 原生Node.js模塊 (即指,須要編譯源碼事後才能被使用的模塊) 須要在編譯後才能和Electron一塊兒使用。
終於搞明白了 Electron 的應用架構,那麼接着就要進入產品的開發階段。比較慶幸的是,ELectron 的UI徹底由CSS+HTML組成,這部分可用的框架太多了,我選擇了又老又知名的 BootStarp 框架搭建界面UI,還引用了JS框架JQuery。選擇了 electron-store 做爲本地存儲文件,至於最關鍵的Markdown語法解析,對比了一番主流解析框架,最終選擇了 markdown-it。貼一下效果圖:
這款軟件我給他起名爲 JustWrite,意思就是如今就寫,也是在督促本身吧,畢竟猶豫徘徊,等於白來。
如今軟件的功能除了包含一鍵發佈本地文章加本地圖片到博客園、CSDN、SegmentFault、掘金、開源中國等平臺,我還打算將他打造爲一個體驗不錯的Markdown寫做軟件。如今你閱讀的這篇文章,就是我使用 JustWrite 書寫的,使用的字體是我我的喜歡的幼圓體,除此以外,還有六款風格迥異的字體能夠切換使用。字號也是能夠動態放大或者縮小,還能夠關閉右側預覽,專一於寫做,以下圖所示:
這些截圖是我截屏後使用快捷鍵Ctrl+V一鍵粘貼的,圖片會自動放到當前md文件所在目錄下的picture文件夾內。
關於 JustWrite 從構思到實踐的心路歷程大體就以上這些了,此次開發 JustWrite 也讓我過了一把產品經理的癮,基本已經知足了個人平常需求。若是你有更好的想法和創意也能夠告訴我,說不定次日就會實現了。