用React x Electron做個PR小工具
用React開發桌面app幫自己省點時間
Talk is cheap. Show me the code.
repo放在前頭是禮貌,react菜雞歡迎批評指教(合掌)
繼去年用Vue + Electron做了個excel轉換器之後,一直覺得Electron是個讓前端無縫寫桌面app的好文明,在開了幾次讓人厭世的PR(Pull request)後,決定來寫個side project以解決撰寫PR內容緩慢的過程。
緣起:
公司專案在開PR的同時,會需要在標題註記該項PR對應的需求票號以自動同步該票的狀態(on dev / on production …),並在內容貼上該票連結,方便QA和需求單位驗收。
平常單項功能進到dev branch的情況,這個額外的小作業並不至於太麻煩,但輪到大進版時,整包release往master推的這種PR,就會需要爬commit或是看file diff來整理這支PR上所關聯的所有票號,整個過程就會變的相當耗時,再加上公司的需求票同時存在於redmine和jira兩套專案管理工具上(這說來話長先跳過),所以往往會花上不少時間在兩套專案管理工具上來回找查需求票,再將其剪剪貼貼到PR中,按照目前兩個禮拜一次的進板節奏,每到那時候就是個開PR到厭世的日子(眼神死
發想:
想讓上述手動作業自動化的念頭油然而生,整理一下工人智慧的情況下都幹了什麼:
- 開出PR,例如dev branch → release branch
- 肉眼掃commit,找出有註記票號的commit
- 辨識票號是哪種格式,是jira票號還是redmine票號
- 前往對應的專案管理工具,找出那張需求票
- 將票號貼進PR標題中、把票號網址貼進PR內容中
- 重複2. ~ 5.項作業,直到commit掃完
轉換成自動化的難點應該還是在資訊的取得,也就是:
- github是否有查詢branch diff的api?
- jira、redmine是否有查詢票號詳細內容的api?
有api的話,剩下的就和平時前端做的事情87%像,沒有的話就只好認份的用puppeteer爬資料了(?
很幸運的,爬文後都有XDDD
上面三者分別需要對應服務的驗證機制,前兩者是Bearer token、後者為Basic auth,所以最好有個介面可以輸入token們和Basic auth的username,再讓我有個介面可以指定repo和branch供api查找…
理一下使用者故事大概就是:
- 可以輸入github token
- 可以輸入redmine token
- 可以輸入jira account、token
- 可以輸入兩個branch name
- 可以用1. 和 4. 的資訊打github api拉回branch diff
- 拉回branch diff後,從其中的commits用正規表達式濾出redmine和jira票號
- 若有redmine票號,用所有redmine票號搭配2. 逐項打api拿回相關資訊
- 若有jira票號,用所有jira票號搭配3. 逐項打api拿回相關資訊
- 將7.、8.的資訊整理成markdown並顯示在畫面上
- 9.的部分可以複製到剪貼簿,最後手動貼到PR上就算完成功能
技術選擇:
大概知道要做什麼之後,就輪到思考要用什麼技術來弄出這東西…
token等相關設定似乎不方便外流,而且又有點懶得部署到網路上…那就是Electron了,在自己桌面上直接啟動App來使用吧!
前端框架的部分倒是毫不猶豫地選了React,因為還沒用React實做過任何作品嘛(自找麻煩XD
Javascript的部分,也來嘗試一下Typescript好了,大不了之後寫成anyscript(不對
接著找尋有沒有現成的Electron + React template,翻了翻github上還不少這種template,就挑個順眼且結合了Vite的模板:electron-vite-react
UI library的部分就爬了些網路文章:
5 best React UI frameworks to build web applications faster in 2022
Top 8 React UI Framework and Component Libraries in 2022
看了看簡介再稍微看看各套件的文件,最後選了文件感覺較親切點的Material UI (隔壁的查克拉UI好搶眼啊!
最後的問題便是CSS library要用誰好,在unoCSS和Tailwind之中猶豫了幾秒…上面好像夠多未知數了,至少CSS這邊先用長期配合的切版好戰友Tailwind吧XD
所以最後的選擇變成:
接著就來開工吧!
v1.0
打鐵趁熱,馬上一天內先弄出了個第一版體驗一下,大致上可以滿足上述一開始提出的功能,另外補上把設定寫入local storage的功能,減少每次打開就要一路貼token的額外麻煩。
心得和難點稍微記錄一下:
- material ui的sx prop還滿強大的,library內部的的component都可以使用這個prop來進行排版,也是tailwind大幅減少出場機會的元兇。
- 正規表達式每次都上網找別人組好的,真的要自創pattern還是只能乖乖面對,靠regex101不斷的try and error才順利完成兩種pattern。
- 連續fetch jira和redmine的作法,原本傻傻地用forEach去逐項打api,但結果就是造成各種非同步狀態管理的不方便,最後使用Promise.all()來進行處理,直接使用一個函式去map票號陣列,回傳一個包含各個Promise fetch的陣列來進行Promise.all(),就可以很好的等待所有票號api都完成後再開始處理所有資料。
- jira和github token如果commit起來推到github上,會馬上寄訊息通知你token已外洩並強制註銷,頗為安心啊XD
- 剪貼板在electron內有自己的api,簡單好用。
- TS的型別檢查真的嚴格,花了不少時間解,不過很高機率是該方法可能回傳null和undefind的情況下,必須確保其型別已經有所列舉。
v2.0
開心的用著v1.0開PR幾分鐘後,就覺得…那些設定沒事可以不用看到吧?還有要對不同repo開PR,每次都要在input上剪剪貼貼也是挺麻煩的,以及branch只有dev、release、production三個選項,其他repo的staging和feature branch我也想用啊啊啊啊!
身為前端,滿足自己的UX應該也是很合理的吧?
於是開始思考優化的方向:
- 設定相關應該可以獨立出一個分頁,設定好應該就不用看它了
- repo和branch應該可以對選項進行CRUD,但Update有點麻煩,CRD就好(?
- 因為2的關係,repo欄位可以從input變為selector
- 該拆出component了,當前的v1.0全部都擠在App.tsx中
方向都有了,那就開始優化吧!
同樣的記錄一下心得和難點:
- 因為主架構變為App內包含ActionPanel、SettingPanel兩個component,但ActionPanel會需要SettingPanel設定的資料,故設定相關資料依舊留在App內,再將資料與其set function用props往兩個Panel component傳下去。
- branch、repo的列表設定介面基本上就是個todo list component,另外將部分icon、placeholder、data、set function抽成props,就可以複用成兩個列表了。
- 子層input onInput事件去觸發父層的set function更新整個object會造成子層re-render,看起來像是輸入一個字元就強制blur的bug,目前解決方法是不即時觸發set function,待輸入完畢後按下儲存鈕再一次觸發所有set function來避免這情況。
v3.0
這版主要是來自同事的兩個需求,有其他使用者當然要好好照顧一下啊XD
來自同事的需求part 1:
白色好傷眼喔,可以有Dark mode嗎?
偉哉Material ui有內建Dark mode,主要是應用的react hooks的createContext,讓ThemeProvider
內的所有元件都可以取得toggleColorMode
來進行切換,並使用已包裝好的useTheme()
來取得相關的設定值,再補上一些對應元件的顏色切換,和之前一樣把設定往local storage內儲存,便能開心完成Dark mode囉!
來自同事的需求part 2:
要追更新很麻煩耶,一般桌面軟體不是都有自動更新嗎?
看了下electron確實有auto update的套件,並且仰賴electron自家的server對指定repo的github release進行比對確認是否有更新釋出,完全不需要自架server來處理這段,實在是非常優秀XD
馬上照著指引安裝套件,再將package.json內的repo設定好…
最後一步便是要設定Builds時的code-signed用以證明這個App無毒友善,macOS需要申請Apple Developer Program來能簽署,趕快來申請一下吧!
果斷放棄實作自動的念頭,直接把錢拿去刷了github copilot,感謝蘋果讓我如此果斷,side project寫一寫順便刷了copilot,真香XDDD
但是自動更新的需求還是沒有解決,重新思考一下,問題應該是在:
使用者不主動查詢的情況下,不會知道軟體發佈更新了
不能自動下載安裝更新,但換成通知使用者有更新,後面的下載安裝交給使用者自助,應該有機會吧?
於是找到有基於原有服務的通知版套件electron-update-notifier,基本設定和原有服務一樣,馬上可以直接沿用,重啟App便會自動偵測到new release並跳出通知啦!
早知道這功能應該先做上去的,相見恨晚莫過於此。
目前這專案就更新到v3.0.1,相較一開始的需求要多做了點東西上去,整體開發體驗也是挺舒服的(除了那個Apple Developer Program),暫時如果沒有其他需求被提出來可能就是偶爾修修bug或是improvement吧!
另外就是electron打包後的檔案肥碩問題暫時好像無解,這專案安裝後居然就要200多MB,讓人意外到不行,下次來試看看其他資深大大建議基於Rust和webview的Tauri,看起來可以有效減低打包體積呢!
最後還有個和開發較無相關的部分,就是為了不想用預設的App icon,請教了公司的UI/UX如何使用figma做點簡單的圖示,成果就是一開始的圖片啦,寫side project就是會點到其他技能樹呢(?
若有其他指教歡迎留言或是發PR,或是有相關需求歡迎許願讓我練練手喔!