electron寫一個簡單host切換工具

做爲一個開發人員,工做中須要常常進行host切換,快速在不一樣環境中進行開發測試,阿里內部有個iHost,用起來簡單順手,惋惜並無開放,離開後沒有找到一款更好的用的host切換工具,索性本身寫一個。項目已經開源前端

代碼地址 , 歡迎吐槽。node

所用到的技術

由於是桌面應用,做爲一個前端開發,目前的首選天然是eletron, 前端框架選擇react技術棧。react

項目基於 electron-react0-boilerplate 生成,用到技術包括:webpack

  1. react 16.x
  2. redux 4.x
  3. redux-thunk 2.x
  4. react-router 4.x
  5. ant-design 3.x
  6. reselect 3.x
  7. redux-actions 3.x
  8. webpack 4.x
  9. node-sass 4.x

主要邏輯和演示

整個應用的難度其實不大,主要就是生成一些條目,基於條目的激活狀態對 host 文件進行讀寫,基本操做以下:git

功能設計

  1. 三個tab頁
    • host設置頁:進行host條目的增刪改查
    • 當前生效的host: 查看系統當前生效的host
    • 原始host: 啓動應用後會備份一份原始host稿件,用於還原
  2. host 設置
    • 可以建立一個host條目,編寫對應的host
    • 能夠對host進行增刪改查
    • 同時能夠建立一個host分組進行統一管理
    • 點擊左側的 checkbox,編輯激活狀態的host設置都會實時改變系統host,不過在編輯時設置了一個 2秒的延遲,避免在不斷的輸入過程當中頻繁讀寫文件

整個應用功能就是這麼簡單,一個關鍵點就是權限問題,要操做host文件須要改變/private/etc/host文件的和/private/etc目錄的權限。因此在應用啓動時會彈出輸入電腦用戶密碼的彈窗進行受權。github

記錄幾個主要技術使用

redux-actions和bindActionCreators

基於redux的項目有一個常常被詬病的地方在於action, reducer的繁瑣,模板代碼太多。redux-actions 是一個不錯的工具用來解決此問題,具體用法請自行學習。不過值得注意的一點是,redux的bindActionCreators 不支持對象嵌套的actionCreator, 例如web

const actionsCreators = {
	add: function() {
		xx
	},
	change: {
		changeTitle: function() {
			xx
		},
		changeDate: function() {
			xx
		}
	}
}

const { add, change } = bindActionCreators(actionsCreator, dispatch)


複製代碼

這裏 change 中的actionCreators是不會綁定成功的,因爲redux-actions生成的actionCreators是能夠嵌套,因此原始的bindActionCreatorsredux-actions 配合起來很不舒服。項目中稍微改寫了一下 bindActionCreators 使其支持嵌套。shell

reselect

對於一些基於計算性的數據,同時把原始數據和計算數據存儲在store上不是一個好的方案,每次更新要進行雙重更新,很容易產遺漏, redux 不一樣於 mobx, mobx 存在computed 裝飾器用於解決計算屬性問題。 這個時候reselect 就派上了用場,不只解決了計算性數據問題,它更大的價值在於可以減小重複計算,每次rerender對於大量數據的計算能夠在入參不變的狀況下不重複計算。不過問題就是會多出一層selectors 層,可能也會讓某些人抓狂吧,嘎嘎~~json

state 持久化存儲

爲了每次打開App的時候保持以前的狀態,整個store層須要存儲下來,所以藉助 electron-json-storage 寫了一個簡單redux 中間件:redux

import storage from 'electron-json-storage';

// 同步 store 到某個文件的持久化存儲中間件, 基於electron-json-storage作存儲

const storageState = store => dispatch => action => {

  dispatch(action);
  
  const nextState = store.getState();
  
  const { menuTree, checkedKeys } = nextState.host.menus;
  
  const { systemHost } = nextState.host.systemHost;
  
  const defaultDataPath = 	storage.getDefaultDataPath();
  
  const dataPath = storage.getDataPath();
  
  console.log('paths:', defaultDataPath, dataPath);
  
  storage.set('HostState-xu', nextState); // 會建立一個HostState-xu.json的文件,儘量保證惟一性,不與其餘應用衝突
};
export default storageState;

複製代碼

每一次action改變都同步保持state

electron-react-boilerplate 帶來的坑點

flow 和 eslint

Flow和一些eslint規則會在前期帶來不少困擾和額外的工做,因此能夠自行斟酌修改一些規則,不過對於Floweslint我的仍是建議多多使用的,會減小不少後期的小問題。

可是項目中的eslint-import插件在結合 webpack 設置alias的時候會出現問題, 一樣對於測試用例,webpackalias配置也不會生效。

幾個處理關鍵點:

  1. .eslintrc 須要改爲.eslintrc.js
  2. .eslintrc.js中引用path 須要require, 不能夠 import
  3. 改爲.eslintrc.js 在vscode中會出現Eslint server掛掉的問題,主要是由於項目中webpack.config.render.dev.js中本身進行了環境變量的檢測CheckNodeEnv('development'), 註釋掉此行代碼。

electron-react-boilerplate 在不斷地更新,最新版的eslint配置可能已經和我當時不一致了,一些處理經驗也有可能過期了,列出一些參考issue: #620 ,#1321 , #1509

圖片的引用

引用圖片的路徑在打包後老是有問題,官方建議在render進程中經過 require 引入圖片,走一遍 loader 生成 base64 的圖片, 直接經過 path.join__dirname 生成路徑在開發環境沒問題,可是打包後會報錯。

然而,在主進程中要使用圖片一樣存在問題,上訴方案並不生效,目前還沒有沒有找到解決方案,已經提了相關issue

貌似electron的靜態資源路徑在開發和生成環境是會有些問題,這裏還須要進一步研究下,有了解的同窗能夠指教下。

shell的exec

本想使用 shelljs 作一些命令處理,可是發現其有electron 兼容性問題 electron-compatibility

由於需求不復雜,直接用 child_process.exec 進行處理。

一個詭異的打包問題

因爲圖片引入問題,我會常常打包驗證,回來發現一個問題,若是上一次的打包出現問題,修改後再次進行打包,發現程序仍然啓動不了,這個時候須要斷網啓動纔會成功。尚不瞭解什麼緣由。

階段小結

第一次寫一個完整的 electron 項目, 用於解決實際需求,仍是挺有意思的,後續項目還要作一些測試,持續集成,自動更新的處理,目前經驗還不足,各位社區的基友,請多指教指教,一塊兒學習!

相關文章
相關標籤/搜索