減少 React 專案的 Boilerplate 從專案配置、API、Redux 來看優化的可能

Lin Yen-Cheng on 2019-06-04 7 min. read

Boilerplate 簡介

Boilerplate 翻譯是樣板,當我們常常重複地做一件事情,作為攻城獅好像就應該把這些東西抽出來,如果不想自己抽,那當然就是找人家寫好的,也少了一道自己維護跟 Debug 的程序。但有了樣板之後,卻發現自己還是一直在複製貼上樣板?這時候突然覺得有點傻眼對吧?能再做的就是再抽一次了。以下分三個常見我認為可以有改進空間的部分:

  • 專案配置: 目標是盡可能減少維護的成本,目標擺在商業邏輯,而非專案配置
  • API: 希望可以統一管理資料處理邏輯
  • Redux: 減少每次都一直寫幾乎一樣的 action、reducer

專案配置

其實寫前端最常遇到首推就是專案配置了,人力少的情況下根本沒必要每次重開一個新專案又自己重新配置一次或因為什麼需求微調、還要注意升級某某套件時的相容性,舉例來說像是如果要處理 SCSS、PWA、伺服器渲染(SSR)、多國語系(i18n)的狀況:

  1. 如果在專案進行到一半才在規劃,很大的可能會遇到各種未知的小問題,像是有些多國語系的資料有些可從前端但有些要從後端來,要怎麼在伺服器渲染時進行處理?
  2. 事先裝相關的套件,做好相關配置,但過了兩個月之後發現,React 跳大版本了,有些相關套件必須升級不可,不然不能用?
  3. 不熟 webpack

如果這時候,在大部分東西都不改的情況下,直接移轉到一些已經做好的配置樣板中,或是一開始就使用有團隊維護的配置呢?或許問題就會減少很多?

  • create-app-script: 相關設定都封裝在 react-scrips 中
    SCSS、網站發佈、環境變數、Bundle 分析、PWA

  • next.js: 封裝 next 裡,是一套框架
    伺服器渲染、多國語系、PWA、路由

  • react-boilerplate: 人工維護版的專案配置,複雜又被解開過的 react-scripts,適合想自力更生又想客製一點小東西的情況

API

打 API 的時候,可能常常不只一個後端,不同後端也會需要有兩個不同的 token,放置的位置可能也不一樣,成功回覆的狀態碼也不同,失敗的情況也不大相同。所以如果當多個地方都需要同時打 A、B 兩個不同的 API 時,也代表多個地方都要進行類似的預/後處理。

axios 透過產生 instance 的方式,幫我們統一處理了 request 發出前,接收 response 後,統一的預處理、後處理的問題。這樣只要在不同的地方使用 A、B instance 去進行 API 的串接即可。

const A = axios.create();

// Add a request interceptor
A.interceptors.request.use(
  function (config) {
    // Do something before request is sent
    return config;
  },
  function (error) {
    // Do something with request error
    return Promise.reject(error);
  }
);

// Add a response interceptor
A.interceptors.response.use(
  function (response) {
    // Do something with response data
    return response;
  },
  function (error) {
    // Do something with response error
    return Promise.reject(error);
  }
);

A.get("/api/path");

Redux

在使用 Redux 的時候,我們通常要同時維護 reducer 以及 action,如果還要搭配 API 進行,又會需要多維護一個 middleware,可是在簡單的專案中,絕大多數時候我們進行的工作都是類似的,redux-api 在這種時候就幫我們少寫很多 action + reducer,也協助我們處理的非同步的部分,簡單來說,本來要維護三個地方,現在變成只要維護一份配置檔就好了。

可以參考之前寫過的文章,如果需要比較多客製化的部分,在官方也有相關的建議:
https://redux.js.org/recipes/reducing-boilerplate

redux-act 則是另外一套函式庫,可以協助我們更快的產生 action 跟 reducer,官方的範例如下:

// Import functions
import { createStore } from "redux";
import { createAction, createReducer } from "redux-act";

// Create an action creator (description is optional)
const increment = createAction("increment the state");
const decrement = createAction("decrement the state");

// Create a reducer
// (ES6 syntax, see Advanced usage below for an alternative for ES5)
const counterReducer = createReducer(
  {
    [increment]: (state) => state + 1,
    [decrement]: (state) => state - 1,
  },
  0 // <-- This is the default state
);

// Create the store
const counterStore = createStore(counterReducer);

// Dispatch actions
counterStore.dispatch(increment()); // counterStore.getState() === 1
counterStore.dispatch(decrement()); // counterStore.getState() === 0

喜歡這篇文章,請幫忙拍拍手喔 🤣

share