Next.js踩坑入門系列(六) —— 再次重構目錄

luffyZh發表於2018-10-10

Next.js踩坑入門系列

上一節引入了redux以及使用redux-saga來進行非同步函式的處理,而上一節的目錄只是簡單的引入redux而已,redux可是相當龐大和複雜的,並且也算是個人習慣了吧。action分離,reducer分離,狀態元件container等等。我喜歡把這些東西劃分的清清楚楚,這樣一個專案維護起來才會方便~這一節就從頭到尾來進行目錄的劃分,因為Next.js和原本的React SPA專案有一定的區別,主要體現在路由部分,所以我也是按照自己的理解和舒服的方式進行目錄重構!

重構完的目錄

// ================ 目錄結構 ================== //
——————
  | -- asserts         // ant-design全域性less變數設定資料夾
  | -- components      // React展示元件(也就是UI元件)資料夾
  | -- constants       // 整個應用的常量資料夾
      | -- ActionsTypes.js   // 存放所有action type的常量檔案
      | -- ApiUrlForBE.js    // 存放所有後端資料的apiUrl
      | -- ...
  | -- containers      // React狀態元件資料夾
  | -- pages           // Next.js路由資料夾
  | -- redux
      | -- actions     // 處理整個應用所有的action
      | -- middlewares // 中介軟體,處理各種特殊情況,比如獲取失敗之後的message提醒
      | -- reducers    // 處理整個應用所有的reducer
      | -- sagas       // 處理整個應用所有的saga
      | -- store.js  
  | -- static          // 存放整個應用所有的靜態資源(如圖片等)
  | -- .babelrc
  | -- .eslintrc
  | -- .gitignore
  | -- next.config.js  // Next.js配置檔案
  | -- package.json   
  | -- server.js       // 服務端server檔案
  | ...
複製程式碼

原諒我臭不要臉一下,個人認為這個結構還是非常清晰的,只不過可能新手寫起來可能會覺得有些繁瑣,不過專案大的情況下,state樹很大,這種結構非常的清晰~

重構actions

其實actions完全可以放在一個檔案裡使用,不過專案龐大了以後維護起來還是有些麻煩的,所以按照元件化思想,每一個元件對應一個action,或者每一個大功能塊對應一個action還是比較合理的。

 -- redux
   | -- actions
       |  -- home.js // 處理首頁action
       |  -- user.js // 處理與使用者有關action
       |  ...        // 其他action
複製程式碼

重構reducers

reducer部分肯定是要分離的,因為redux的官方為我們提供combineReducer這個API就是合併不同元件的reducer的,所以可以理解為redux的reducer推薦就是根據元件進行劃分的~就如同整個應用只有一個狀態樹一樣,每一個reducer負責處理樹的不同枝葉派發出來的action。具體reducer內容還是去看redux官方文件吧。

重構sagas

 -- redux
   | -- reducers
       |  -- home    // 首頁部分reducer
       |  -- user    // 使用者相關reducer
       |  ...        // 其他reducer
       | index.js    // rootReducer,由combineReducer生成
複製程式碼

抽離container

這裡需要特別說明一下~~~由於Next.js的特殊原因,其實已經做到了UI元件的分離,其實這一層container完全可以由pages資料夾代替,也就是可以用路由元件通過react-redux的connect函式封裝一下,這樣就變成了一個帶狀態的路由元件,不知道大家明不明白我說的話。。。下面是兩種方法,大家按需自己採取,以UserList元件為例:

  • 第一種,抽離container
    // /conatiners/user/UserList.js
    import { connect } from 'react-redux';
    import { fetchUserListData } from '../../redux/actions/user';
    import UserList from '../../components/User/UserList';
    
    const mapStateToProps = state => ({
      list: state.user.list.list,
    });
    
    const mapDispatchToProps = dispatch => ({
      fetchUserListData() {
        dispatch(fetchUserListData());
      }
    });
    
    export default connect(mapStateToProps, mapDispatchToProps)(UserList);

    // pages/user/userList.js
    import UserList from '../../containers/user/UserList';
    import { fetchUserListData } from '../../redux/actions/user';
    // 這部分內容下一章節講~
    UserList.getInitialProps = async (props) => {
      const { store, isServer } = props.ctx;
      if (store.getState().user.list.list.length === 0) {
        store.dispatch(fetchUserListData());
      }
      return { isServer };
    };
    
    export default UserList;
複製程式碼

簡單來說其實就是路由元件匯入的是狀態組建UserList.js,而狀態組建是通過react-redux的connect方法封裝UI元件UserList.js而得來的。

  • 第二種,帶狀態的路由元件
// /pages/user/userList.js
import { connect } from 'react-redux';
import UserList from '../../containers/user/UserList';
import { fetchUserListData } from '../../redux/actions/user';

UserList.getInitialProps = async (props) => {
  const { store, isServer } = props.ctx;
  if (store.getState().user.list.list.length === 0) {
    store.dispatch(fetchUserListData());
  }
  return { isServer };
};

const mapStateToProps = state => ({
  list: state.user.list.list,
});

const mapDispatchToProps = dispatch => ({
  fetchUserListData() {
    dispatch(fetchUserListData());
  }
});

export default connect(mapStateToProps, mapDispatchToProps)(UserList);
複製程式碼

簡單來說,就是在路由元件內把UI元件UserList.js通過connect變成了狀態元件。

個人推薦第一種方法,雖然寫起來稍微麻煩了一些,但是第二種方法完全是因為Next.js的特殊性才能實現的,當然,對於Next.js來說,第二種方式確實更簡單一些~

結束語

經歷了上面幾個部分的重構,整個基於Next.js的服務端渲染腳手架基本結構也就成型了。在搭建過程中還是遇到了很多坑的,不過也都一點點的踩過去了。希望對大家有些幫助,個人認為這個結構還是值得參考一下的~原本到這裡就可以結束系列文章了,不過我在使用過程又發現了一些坑,順便的Next.js還有一些內容我還沒碰過,就幫大家都踩一踩,下一節來一個其他內容的大雜燴~

程式碼地址

相關文章