如何加速 React.js 開發 — 我們遇到的三個問題與解決方案

李至青
Visually Lab
Published in
6 min readJan 3, 2020

--

Photo by Vidar Nordli-Mathisen on Unsplash

ReactJS 是我們團隊內開發網頁時使用的函式庫,它提供了宣告式的 API 並讓網頁開發可以組件化,讓網頁的開發能夠夠容易規模化,除此之外, React 擁有活躍的生態系,大部分你遇過的問題,你需要的工具,都能在社群中找到。

在這篇文章中,我將會分享在團隊我們使用的技術,以及它解決了我們什麼問題。

1. Javascript 弱型別的特性讓程式碼容易有型別的錯誤,而且難以重構

0 == [] 
// True

這是一個 Javascript 弱型別的例子,寬鬆的型別檢查可以讓開發更快速嗎?一開始可以,但隨著程式碼變得複雜,Debug 難度會隨之提高。

同時,在需要重構部分程式碼的時候,因為不確定資料型別,需要更多時間去了解程式的上下脈絡,才能有自信的重構。

如果在不知道資料型別時重構,那就是在睜一隻眼閉一隻眼,自己騙自己。

我們採用 Typescript 作為型別檢查的解決方案

他能夠加速開發嗎?一開始可能與上方的敘述相反,當你一開始寫 Typescript 時,你會覺得慢了許多,因為你必須要定義 typing,然而些努力都會在 codebase 成長後得到回報,你會感謝從前的你(或你的同事)的努力,然後在往後的專案,你都會覺得必須要使用 Typescript

Typescript is Javascript that scales.

Typescript 除了能夠透過語法就能檢查出型別的錯誤,還有一個巨大的優點, IntelliSense & autocomplete。如果你使用 VScode,Typescript 能夠提供可用的變數、屬性或者 module 的提示,這能夠大大加速開發時間,讓開發者可以專注在架構跟商業邏輯的實現,而不是在想變數的英文字母有沒有拼錯。

2. 需要 lint 保持程式碼風格一致,但要一一處理 warning 很麻煩

在團隊合作開發軟體時,保持程式碼風格一致很重要,如果能有一致的程式碼風格,會讓程式碼更加容易理解,並且在開發時能專注在程式邏輯,而非程式碼的語法差異。

Lint 是檢查程式碼風格的工具,讓團隊可以設置偏好的規則,然後透過 Lint 檢查。因爲我們使用 Typescript ,所以我們採用了 TSLint ,但要注意的是 TSLint 即將停止開發,因為 ESLint 將會支援 Typescript,如果要初步引進 Lint,可以考慮直接使用 ESLint。

使用 Lint 的好處顯而易見,但缺點也是。針對於無法自動修正的錯誤,開發者必須一一找到錯誤的地方並且手動修正,這個過程耗時且讓人感到挫折。後來我們發現,不只我們有這個困擾。

1. Open your ESLint config

2. Disable all styling rules (or add eslint-config-prettier which does that)

3. Install Prettier You’ll thank me.

Linters are there to help you find mistakes in your code. Not to torture you.

- Dan Abramov

於是我們考慮使用 prettier

prettiier 是一個程式碼格式化工具。

程式碼的格式化與 lint 的最大差異在於,前者以產出一樣的風格為目標,後者以檢查特定的規則為目標。而這兩個工具可以同時使用,用 prettier 產出固定風格的程式碼,然後如果有額外必須要遵守的規則,就讓 Lint 提醒我們吧。

如此一來,大大減少了手動修正 lint 錯誤的工作量,也提供了一致的程式碼風格。

最後,我們還希望能夠自動執行 prettier,我們利用了 lint-staged husky ,讓我們每次 commit 時都會先格式化程式碼,確保 codebase 中所有的程式碼都是格式化過的。

如果你對設置的過程以及我們的使用的參數有興趣,可以參考:

3. 使用 React 開發 component 時,lifecycle 中的邏輯無法重複使用

render props 與 high order component 都可以解決這個問題,但在 React 16.8 正式發佈之後,這個問題已有了標準答案:採用 React hook

Hook 是 React 16.8 中增加的新功能。它讓你不必寫 class 就能使用 state 以及其他 React 的功能。 -https://zh-hant.reactjs.org/docs/hooks-intro.html

我們在 component 的實作上,全面改用 functional component 與 hook

我們決定全面採用 hook 和 functional component,因為 hook 讓開發者能夠使用簡潔的語法創造出可以重複使用的功能(functionality)

同時我們不必重構舊有的 class component,官方並不建議我們重寫 class component,因為他們仍舊會繼續支援 class component。

如何使用 Hook 創造出可以重複使用的功能?

Hook 讓 reuse 功能變得可行的關鍵在於,Hook 將原先 class 提供的 lifecycle 和 state 功能,以更細緻的方式以 hook 拆分出來。例如:

在 class 中的功能實作:

若以 hook 實作變成:

從這個例子中可以看到,hook 將原先混雜在 lifecycle 中的邏輯,抽象化成兩獨立,自給自足的 hook,這讓功能的抽象化在 React 中變得更容易,可行了。

Hook 讓 React 開發者可以用更少的程式碼,創造更容易維護的 component,更容易規模化的應用程式。

最後,整理在這篇文章中我們遇到的問題與解決方案:

  1. 使用 Typescript 預防 javascript 的型別錯誤,讓重構程式碼更加容易,並且在開發時能夠讓編輯器提供 IntelliSense & autocomplete。
  2. 使用 prettier, tslint, lint-staged husky 以自動格式化加上少部分的人工修改,確保 codebase 有一致的程式碼風格。
  3. 使用 React hook 以更少的程式碼,創造更容易維護的 component,更容易規模化的應用程式。

--

--