多是東半球最好的 React + Redux 啓動器,基於 Vue Cli 二次開發

React 示例項目 · 簡易留言板 + 待辦事項(Github 地址

寫在前面

一直以來,我都至關納悶:爲何 React 的那些 starter kit 都構建得那麼噁心?
能不能像 Vue Cli 生成的項目架構般優雅?說幹就幹,本項目就改自 Vue Demophp

§ 技術棧

詳情可參閱 package.jsonhtml

  • React 15.3.0前端

  • Reduxvue

  • React Routernode

  • Ajax 請求庫(Superagent / jQuery-Ajax / ...)python

  • Webpackreact

  • ES6 + Babelwebpack

  • jQuery + BootStrap (UI)git

§ 快速開始

在開始前,但願您已通讀以下資料github

同時您還須要熟悉 ES6。例如,請把以下代碼
const foo = ({ hello: { world: bar } }) => ({ bar })
轉譯成 ES5(答案請自行到 Babel REPL 在線編譯驗證)

⊙ 安裝

建議升級到 node 5.x/6.x + npm 3.x 環境
推薦使用 cnpm 或手動切換到淘寶 npm 源
npm set registry https://registry.npm.taobao.org/

本示例項目須要結合 簡易留言板 RESTful API
模擬先後端分離開發(還爲了與 Vue Demo 共用)
請分別 git clone,打開兩個命令窗口( Windows 下推薦使用 Cygwin分別切換到二者的目錄下
分別敲下 npm install 安裝依賴(爲避免 Windows 下的 npm 軟連接問題,可加上 --no-bin-link 徹底解構全部依賴)

雖然咱們已經切換到了淘寶 npm 源,但安裝 node-sass@3.8.0 的時候仍是頗有可能卡住
由於它的安裝須要從 Github 的 AWS 服務器拉取二進制文件,所以您能夠爲它指定源:
npm i node-sass@3.8.0 --registry=https://registry.npm.taobao.org

若是您想簡單粗暴一點,這裏還提供了 node_modules.zip,直接解壓便可

⊙ 啓動

前後在 msg-board-apireact-demo 的命令窗口下,敲下 npm start
如無心外,默認瀏覽器就會自動打開 localhost:9090,您當即能夠看到效果
若瀏覽器沒有自動彈出,則請自行手動訪問

開發過程當中,經過 Webpack 處理的靜態資源都由基於內存的 webpack-dev-server 提供
P.S. 若是您還不清楚如何安裝與啓動,請看這個 issue

§ 項目架構

⊙ 目錄結構

.
├─ build/            # Webpack 配置目錄
├─ dist/             # build 生成的生產環境下的項目
├─ src/              # 源碼目錄(開發都在這裏進行)
│   ├─ components/     # 組件(COMPONENT)
│   ├─ redux/          # Redux 一籮筐
│   │   ├─ actions/      # (ACTION)
│   │   ├─ reducers/     # (REDUCER)
│   │   ├─ store/        # (STORE)
│   ├── routes/        # 路由(ROUTE)
│   ├── services/      # 服務(SERVICE,用於統一管理 XHR 請求,這是從 Vue Demo 中直接複製過來的)
│   ├── utils/         # 工具庫(UTIL)
│   │   ├─ HoC/          # 高階組件(HOC,全稱 Higher Order Component)
│   │   ├─ mixins/       # 混合(MIXIN)
│   ├── views/         # 路由視圖基頁(VIEW)
│   │   ├─ layout/       # 全局佈局
│   ├── app.js         # 啓動文件
│   ├── index.html     # 靜態基頁
├── static/          # 放置無需經由 Webpack 處理的靜態文件
├── .babelrc         # Babel 轉碼配置
├── .eslintignore    # (配置)ESLint 檢查中需忽略的文件(夾)
├── .eslintrc        # ESLint 配置
├── .gitignore       # (配置)需被 Git 忽略的文件(夾)
├── package.json     # (這個就不用多解釋了吧)

在這裏您可能會問:怎麼沒有 containers/ 目錄?
在個人理解裏,木偶組件與智能組件最大的差異在於:
前者的狀態是經過父組件傳入得到,然後者是直接鏈接state 得到
亦即:若一個木偶組件直接鏈接state,那麼它就是一個所謂的智能組件
(詳見 src/utils/makeContainer.js 中對 react-reduxconnect 函數的封裝)
本示例項目惟一在組件的定義中自行使用 connect 函數的是 Navbar 組件(且用到了 ES7 的裝飾器)

您能夠根據業務需求改動目錄結構。若目錄使用頻繁,建議配置 路徑別名
默認的路徑別名見上面目錄結構註釋中大寫形式的常量

⊙ 特點

  • 本示例項目秉承最佳實踐,高度潔癖地實現代碼分離/複用

  • 優化目錄結構,更好的模塊分離,更接近 Vue 的開發模式

  • Redux DevTools,可選 Chrome 插件形式(默認) 或 內嵌頁面的組件形式

  • Redux Logger 打印動做及先後狀態變化

  • why-did-you-update 檢測沒必要要的組件重渲染(默認關閉)

  • 引入服務層統一管理 XHR 請求(好處請參考 Vue Demo 中的 引入服務層

  • 引入 路徑別名 實現優雅的加載模式

  • 引入 React Hot Reload,支持熱替換

  • 生產環境下的編譯對代碼進行優化

  • 迄今爲止我見過的最完美的 starter kit

有關 Redux DevTools 與 why-did-you-update 的啓用與禁用,見下面的 開發環境全局變量 配置

§ 開發

⊙ Webpack 配置

因爲已經擁有相對成熟的 Webpack 配置,所以在必定程度上您能夠不求甚解,但瞭解其配置會更能把握總體開發

  • 前端開發服務器爲 localhost:9090,可在 build/webpack.config.dev.js 中找到

後端 RESTful API 基地址寫在了 src/services/xhr/config.js 中,請根據實際自行修改

  • 框架 / 類庫 須分離打包以加快開發時的編譯速度並有利於緩存,詳見 build/webpack.base.conf.js 中的 vendor

  • 路徑別名 的定義位於 build/webpack.base.conf.js,好處就是引入與重構都很方便

例如,在某組件中,引入 userService 須要 import userService from '../../../services/userService'
但有了路徑別名後,只須要 import userService from 'SERVICE/userService'
相比於 AngularJS 中的依賴注入,這種方式依賴於構建工具,顯得更爲簡單

您可能會說,Webpack 只須要設定了 root屬性爲 src/
就能夠 import userService from 'services/userService'
但在這裏實際上是會引發歧義的(不過這屬於強迫症的範疇。。。)
例如,import createBrowserHistory from 'history/lib/createBrowserHistory'
您可能會以爲這是 src/history/lib/createBrowserHistory.js
但實際上 history 是一個 npm package
一樣地,您又怎麼知道 services 不是一個 npm package?
並且重構以後,文件夾的變更會致使相對路徑的變化,services/ 目錄未必仍在 src/
所以,路徑別名至關有必要。其常量的形式,讓人一看就知道不是一個 npm package

  • 開發環境全局變量,由 webpack.DefinePlugin 提供(詳見 build/webpack.base.conf.js

默認有 __DEV__ / __PROD__ / __COMPONENT_DEVTOOLS__ / __WHY_DID_YOU_UPDATE__ 四個全局變量
若要繼續添加,則還須要在 .eslintrcglobals 同步寫入

在此須要提醒,在 package.json 中設置 NODE_ENV 要注意末尾空格的問題
最好就是使用前 trim 一下:process.env.NODE_ENV.trim()

拓展閱讀:解讀 UglifyJS
看看生產環境下編譯 if (__PROD__) { ... } => if (true) { ... }UglifyJS 會如何處理

⊙ 規範

本示例項目的代碼極盡詳細地添加了註釋,其中不乏最佳實踐提示

爲了減小代碼量,我省去了 Prop 驗證,建議您在日後的開發中使用

§ 測試

請自行選擇測試工具

§ 部署

react-demo 的命令窗口下,敲下 npm run build,將會在項目根目錄下生成 dist/

您可使用命令行靜態資源服務器 serve ( npm i serve -g ),敲下 serve -p [端口] dist 來快速查看 build 後的項目
還能夠 cd dist 後,python -m SimpleHTTPServer [端口]php -S localhost:[端口] 快速便捷地實現靜態資源服務器

關於生產環境下的部署與優化,已超出本文檔的論述範圍,請自行查閱相關資料
在這裏您可能須要全局安裝 rimrafnpm i rimraf -g(或根據指引配置環境變量避免全局安裝)

§ 參考

相關文章
相關標籤/搜索