[專案紀錄] 記帳 app 重構!功能畫面小升級

I caught a code
I Caught a Code
Published in
10 min readJul 26, 2021

--

勇敢重構,打造新功能

先放上專案連結和體驗帳號:

GitHub RepoLive Demo on Heroku

體驗帳號:user1@example.com
體驗密碼:12345678

最近翻修三四個月前寫的小專案,不看程式碼還好,一看驚為天人。

天啊這什麼垃圾 code !

Bootstrap 和一堆散落各地的 CSS 檔好像命案現場

而且因為沒做 RWD,用小螢幕開還會破版喔。簡直就是慘中之慘 🙃 或許之後也會需要維護一些舊專案、進行更新,趁這個機會把自己以前挖的坑填好,修整一下吧:

將所有 promise-based 語法改成 async/await

自從體驗過 async/await 用變數精準的接球(?)後就回不去勾勾纏的 .then() 傳遞資料的方式了。因此就將有使用到非同步撈資料的部分都改成了 async/await 語法,有了清楚的變數承接撈回來的資料,搭配 try/catch block,程式碼整體易讀性變高、架構更清楚了。

但這麼一來也開始思考,如果所有非同步的程式碼都需要用一個變數來接住他的回傳值,是不是會多出很多無意義的變數?例如在加密 password 的時候,bcrypt 的灑鹽和 hash 手續:

用 async/await 的方式後,就多出了 salt 跟 hash 這兩個變數

後來在重構的過程中,也更改了撈取資料的方式,以及一些變數名稱的優化,以及加入了 validator 套件來驗證登入和註冊資訊。從這些小細節中也可以看出這幾個月的學習,會讓自己不斷反思過去寫的 code 真的是好 code 嗎?雖然現在改完的有「稍微」精簡一點點,但我想再過幾個月回來看,一定還能再更優化的。

加入統計收支類別的圖表

上一個版本的功能很陽春,只有添加「支出」的項目,也沒有什麼視覺化的呈現。這次決定加入「收入」類別,以及動態圖表,可以呈現篩選類別、月份、收入支出的結果。

加入不同的記帳類別首先就是更新 records 資料表,加入 recordType 的欄位,在資料儲存的當下就存入該則紀錄為 expense 或 income,作為之後篩選條件的指標。

圖表的部分,在收集資料後決定使用 Chart.js 這個套件,可以用傳入的資料渲染出精美的圖表,種類非常多,這次使用的是 doughnut chart 來呈現不同類別的佔比

本來希望直接在後端路由將資料撈好,傳送到前端 handlebars 樣板,利用 {{#if records}} ...{{ this.name }} {{/if}} 的方式來將資料渲染出來。

但因為 Chart.js 是使用 <canvas> 標籤來裝整個圖表,渲染方式類似 react app 只有一個空標籤 <app>,內部的東西則靠其他的程式碼打包後渲染,所以是無法在裡面塞東西的。後來改用選取 DOM 元素 inner HTML 的方式取出後端傳來的值就成功囉:

從後端將各類別的收支用陣列傳入

加入 Google 登入驗證

集滿三種登入方式了!

之前使用 Passport.js 實作本地端與 Facebook 的登入驗證,那不能不試試看 Google 登入吧!在翻過官方文件後決定使用 Google 的 OAuth2.0 驗證方式:

取自 Passport.js 官網

用 npm 載入passport-google-oauth 套件之後,還需要到 GCP Console 去申請一個 app,才能取得 client id client secret,這部分和 Facebook app 的流程差不多。而在申請過程中也須填寫這個 app 取用資料的 scope,可以決定要取用哪些使用者資訊。 一開始選擇最基本的 scope 時,發現要撈 email 時撈不到,原來最基本的選項回傳的 profile 資料是沒有包含 email 的,這也是發揮遇 bug 先console.log() 的精神才找出來XD

然後就能夠看到這個畫面了:

人真的不能高興的太早 :) 此時無法進行下一步,因為還要去 GCP console 一併設定 callbackURL,否則登入後不論成功失敗是無法跳轉到下一個頁面的,設定完後就能正常登入囉。

Google 驗證與 Facebook 一樣,都須創建一個新的 user 資料,並因為之前資料欄位的設定 password 為 required,因此也需要設計一串使用 bcrypt 加密過的假密碼,加上 Google 帳號驗證後配發的 google.id 一併存入資料庫,之後登入時便會認這個 google.id。

加入個人資訊編輯頁面

目前功能還是很少,有點無聊,所以為了再次練習 <input type=”file”> 與串接 imgur node API 的使用方式,多做了一個使用者資訊編輯的頁面,變得稍微客製化一點:

原本還有更改密碼、確認密碼的欄位,也有做欄位驗證,但在某一天出借體驗帳號被改了密碼登不進去(資料庫中也不會有明文密碼)後,想想覺得暫時先將一些帳號相關的欄位設定為不可更改,留下名字、大頭貼這類可客製化的東西就好。

用 Tailwind CSS 進行樣式大翻新

本來是用 Bootstrap 來配置整體版型,因為有很多現成的 UI 可使用,例如 nav bar 、form 之類的,但 Bootstrap 的版型雖然簡單好看,卻有點死板(也可能是我沒有太深入專研,只用來快速切版XD),我想把樣式改的個人化些,對 CSS 微調的需求大增,因此除了 bootstrap 之外也開始在 HTML 檔中累積了很多個 inline CSS 設定… 點開 HTML 時都會眼神死,東西好多。

於是之前就把所有的 inline CSS 切分出去放在獨立的 CSS 檔案中再引入,HTML 中就留下當時切版必要的 Bootstrap 設定。但這樣還是滿雜的,有時候需要兩個檔案都開著搭配著看,才知道這個元素背後的設定有哪些。

之前是有幾個頁面就拆成幾個 CSS,雖然維護容易(內容不多)但還是繁雜

所以就上網搜尋有沒有更平易近人的 CSS 框架,找到了 Tailwind CSS,官網中文化後的各個小標更吸引人了XD 例如:

擔心複用性的問題? 免了啦

如果你想要一直、一直、一直地重複使用你的功能或設計,那你需要的是把它們做成元件或樣板,這樣你只要改變一次,就能應用在所有地方。

寫的這麼聳動,好吧我就試試看了 :)

使用新套件前,最好都先閱讀一下官方文件。大致看了一下官方文件了解 Tailwind CSS 的引入方式及常用的 CSS 設定如何用他們的語法撰寫後,就到 Tailwind CSS 的官方 Youtube — Tailwind Labs 觀看 Crash Course。不得不說,官方教學教的很淺顯易懂,示範也都非常詳細,真的是新手福音。

看個教學,馬上來練習切了一個 KKday 手機版網頁的版型,讓自己快速熟悉語法:

大致上都和 Bootstrap 差不多,但它的厲害之處不是這裡,而是剛剛聳動標題寫的複用性,用 npm 載入 Tailwind CSS 後其實還有幾個檔案 tailwind.config.js ,裡面可自定義一些元件,存成常用的語法來使用。另外也需手動新增 tailwind.css,將常常重複使用到的 CSS 設定存成 class name,直接寫在 HTML 元素的 class list 中使用!

最後則透過後處理器 postcss 來將 tailwind.css 中的這些打包過的設定,output 成 style.css,跑過以下指令(指令名稱可自定義)後,就能成功重複使用樣式設定:

"tailwind:build": "postcss public/stylesheets/tailwind.css -o public/stylesheets/style.css"

然後整個 HTML 檔就乾淨多了… 也可以把不需要的 CSS 檔們都先刪掉了,圖片則是都丟到 /assets 裡做統一的管理:

剩下一個自己寫的 CSS 檔 QQ 大掃除完好開心

這時因為舊的 Bootstrap 版型在拿掉 CDN 後慘不忍睹,我就先大致看一下原來的設定,用 Tailwind 的語法再刻一次,其實兩者的語法差不多,有些用字不同而已,切起來還算快。也終於在這次遵循 mobile-first 原則,先從小螢幕開始切,之後用 Tailwind 的 CSS grid 來進行 RWD 中大螢幕版型的配置:

雖然對 Tailwind 強大的功能目前只有粗淺的認識,但之後應該有機會搭配前端框架的學習使用。這次有練習到不同的 grid 排版方式,最近在 AC 當助教開始改學期 2–1 的作業,需要搞懂 CSS grid 與 Bootstrap grid 的用法,剛好當做一次不錯的複習。

小翻新紀錄就到這,謝謝收看~這主題應該看到煩了,是最後一篇XD

有興趣看這個專案過程的可以收看以下三篇紀錄:

[專案紀錄] 記帳 web app 升級!實作登入功能 — 專案緣起&回顧篇

[專案紀錄] 記帳 web app 升級!實作登入功能 — (一) 註冊篇

[專案紀錄] 記帳 web app 升級!實作登入功能 — (二) 登入/登出篇

後記

雖然我對後端領域更有興趣,但我想基本的前端技能還是得找時間練習,因為不管寫出多厲害的功能,還是得靠一個前端畫面來呈現給其他人看,人就是視覺化的動物啊。最近也預計學習前端框架,除了了解如何管理共用元件,也想了解串接資料的方式,學習真是條不歸路,但我喜歡 :)

--

--