RIS,建立 React 應用的新選擇

止戰之殤發表於2019-02-21

前言

RIS, React Integrated Solution. 它的目標是提供一套基本的構建配置方案,而且配置是能高度擴充套件的,希望通過它能對外輸出 React 的一些最佳實踐。

RIS 是我在去年11月開始開源出去的,這工具之前在內部團隊使用過,反饋還不錯,斷斷續續維護和寫文件,現在介紹給大家,希望能給大家提供一些幫助和啟發。

背景

目前社群已經有很多優秀的工具或框架做前端構建的事情,而且整合了相關的最佳實踐,比如 create-react-appreact-boilerplateumi 等等,這三個我都覺得做得很不錯,我做 RIS 的時候很多想法都來源於它們。那為啥我還要重複造輪子?輪子不怕造,最重要是能說服自己,我覺得自己可以做出跟別人不一樣甚至有創新的東西出來,其次,在造的過程中,也是自己對於前端構建一些思考的沉澱。

在這說下自己的一些想法:

  • create-react-app: 它的構建和開發體驗我覺得是做得最好的,也得到了社群的認可,但我覺得唯一缺乏的是擴充套件比較麻煩,受限於裡面內建的構建,當然有人說可以使用 enject 的方式,但這樣又失去了工具的意義了。
  • react-boilerplate:它的亮點主要是整合了一些最佳實踐,基本包含了專案開發中所需的技術,但只是一個工程,沒有工具化。
  • umi:它是支付寶做的企業級應用框架,可以通過外掛整合相關的功能,約束比較強,自主權很小。

RIS 要做到的是更像是 create-react-app 的方式,提供最底層的構建,同時提供通用的一些開發方案, 再給予開發者足夠的自由定製自己想要的,希望通過這個工具輸出 React 開發的最佳實踐。

快速體驗

npx create-ris ris-app
cd ris-app
npm start
複製程式碼

npm 的版本需要是 5.2 及以上

kk

詳細可參考文件

特性

主要的特性:

  • ✔ ︎開箱即用,內建了空白模板和標準模板,整合 react, react-outer 等。
  • ✔︎ 高擴充套件性,可以高度定製專案內容和構建配置。
  • ✔︎ 極致的開發體驗,使用了 DLL 加快構建速度,可以使用命令快速新建元件和頁面。
  • ✔︎ 高效能,使用了 react-loadable 實現程式碼的按需載入。
  • ✔︎ 強大的資料模擬功能, 很方便地在開發環境模擬資料。
  • ✔︎ 高效的資料流處理,整合了 xredux,很好地處理資料流問題。

開箱即用

使用 create-ris 可快速建立腳手架,目前整合了 空白模板標準模板

npx create-ris <appName>
複製程式碼

空白模板(simple)

建立出來的專案和 create-react-app 建立的差不多,只是一個空白專案。

├── README.md
├── package.json
├── src
│   ├── App.js
│   ├── App.scss
│   ├── index.html
│   └── index.js
└── tools
    ├── generators
    │   ├── component
    │   │   ├── class.js.hbs
    │   │   ├── index.js
    │   │   └── stateless.js.hbs
    │   ├── index.js
    │   └── utils
    │       └── componentExists.js
    ├── risrc.js
    ├── server
    │   └── index.js
    └── webpack
        ├── base.js
        ├── dev.js
        └── prod.js
複製程式碼

標準模板(standard)

主要整合了 react-router, react-redux, xreduxreact-loadable 等庫,主要提供單頁應用的標準解決方案。

├── README.md
├── mock
│   └── rules.js
├── package.json
├── src
│   ├── assets
│   ├── components
│   ├── core
│   │   └── request
│   ├── index.html
│   ├── index.js
│   ├── pages
│   │   ├── Demo
│   │   │   ├── Loadable.js
│   │   │   ├── index.js
│   │   │   ├── index.scss
│   │   │   └── model.js
│   ├── routes.js
│   ├── services
│   ├── store
│   └── utils
└── tools
複製程式碼

詳細目錄可以建立專案來體驗一下。

高擴充套件性

高擴充套件性體現在兩方面,一方面是專案的高擴充套件性和構建的高擴充套件性。

第一,從建立出來的專案可以看出來,沒有對任何使用的技術進行封裝,使用的都是業界比較認可的技術,版本可以自主控制,開發者可以自由選擇專案的技術棧。

第二,構建上是可以高度定製的,目前是通過靈活合併專案中的配置的方式進行定製,下面主要介紹下如何定製構建配置。

在專案根目錄下有個 tools 資料夾,裡面有 webpack, servergenerators 資料夾。下面主要介紹 webpackserver 如何配置。

webpack

webpack 資料夾有三個檔案 base.jsdev.jsprod.js,分別對應基礎配置,開發環境和生產環境的配置。

base.js

const path = require('path');

const resolveApp = relativePath => path.join(process.cwd(), relativePath);

module.exports = {
  entry: resolveApp('src/index.js'),
  module: {
    rules: [],
  },
  resolve: {
  },
  plugins: [],
};
複製程式碼

格式是和官方配置格式是一致的,構建時會對這些配置進行合併。類似這樣:

merge([built-in config], merge(base.js, dev.js));
複製程式碼

server

server 的配置也是一樣的,提供官方配置格式,然後進行合併。

module.exports = {
  port: 3000,
  compress: true,
  quiet: false,
  clientLogLevel: 'none',
  disableHostCheck: true,
  historyApiFallback: {
    disableDotRule: true,
  },
  proxy: {
  }
};
複製程式碼

通過這樣的方式,很容易實現新增 loaderplugins,從而很容易把 ant-design 等元件庫整合到專案中來,詳細可參考使用者文件

極致的開發體驗

在開發體驗上主要有兩個亮點,

第一,開發環境中自動使用了 DLL,使得專案程式碼的二次編譯速度有了質的飛躍。

在開發環境中,自動將所有第三方依賴打入 DLL,和業務邏輯程式碼進行分離,不參與二次編譯,所以開發過程中構建速度會非常快。

當然,可以自由配置哪些需要打入 DLL,甚至可以禁用此功能,詳細參考一下文件

tools/risrc.js

module.exports = {
  dll: true,
  dllPlugin: {
    path: 'node_modules/ris-react-boilerplate-dlls',
    exclude: [],
    include: [],
    dlls: null,
  },
};
複製程式碼

第二,提供了 生成器(generators) 功能,可以快速建立元件和頁面。

很多時候,我們新建一個頁面元件,都是通過拷貝的方式,把之前的頁面程式碼拷貝過來刪除修改,這樣效率非常低而且不可控。

這裡我們可以通過 add 命令根據設定好的模板快速建立組建和頁面,

npm run add
複製程式碼

kk

元件和頁面的模板可以在專案中 tools/generators 裡進行配置,詳細參考文件

這兩塊功能的想法來源於 react-boilerplate

高效能

出於效能上考慮,單頁應用龐大起來的時候,bundle 的體積是很大的,所以使用了 react-loadable 對模組進行動態載入。

import Loadable from 'react-loadable';

export default Loadable({
  loader: () => import('./index'),
  loading: () => null,
});
複製程式碼

詳細可參考文件

強大的資料模擬功能

資料模擬在開發過程中是非常重要的一環,在服務端沒有準備好介面資料的時候,我們往往需要自己在本地模擬資料,這裡我寫了個小工具 @ris/mock 來實現這個功能。

只要在專案根目錄下的 mock 資料夾配置下 rules.js 檔案即可。詳細參考文件

mock/rules.js

module.exports = {
  'GET /api/user': { name: 'beyondxgb' },
  'POST /api/form/create': { success: true },
  'GET /api/cases/list': (req, res) => { res.end(JSON.stringify([{ id: 1, name: 'demo' }])); },
  'GET /api/user/list': 'user/list.json',
  'GET /api/user/create': 'user/create.js',
};
複製程式碼

高效的資料流處理

在資料流上的處理,沒有直接使用 redux,因為使用過都知道,建太多檔案太繁瑣了,而且沒有很好地處理非同步資料流,在此之前,dva 提出了 model 的概念,我覺得這已經是非常好地解決了 redux 的問題,後來出的一些庫也離不開 model 的概念,但 dva 或者 mirrorx,它們的定位是大而全的框架,其實是解決 redux 的問題,卻要混著其他東西打包成一個框架,這樣顯得不純,這裡我自己寫了個 xredux,參考了 dvamirrorx 的一些想法,封裝出一個庫,只是單純解決 reudx 的問題,不依賴於任何框架,可以看作是 redux 的升級版。

用法上和 dvamirrorx 差不多,大概如下:

import xredux from 'xredux';
const store = xredux.createStore();
xredux.model({
  namespace: 'app',
  initialState: {
  },
  reducers: {
  },
  effects: {
  },
});
複製程式碼

很好地把 actionreducersstate 結合到一個 model 裡面,在非同步請求的處理上也非常地優雅,詳細使用可參考文件

結語

RIS 是我自己工作上的沉澱,開源出來給大家互相學習,希望能給部分人帶來幫助和啟發,裡面所使用的技術也是個人的主觀想法,不喜勿噴。後面會逐漸將自己的一些最佳實踐沉澱在這裡,也歡迎大家貢獻自己的想法。

如果喜歡 RIS 的話,歡迎使用,有問題可以提 issues,也非常歡迎進行共建。

如果不喜歡 RIS 的話,可以好好閱讀下原始碼,做前端構建工具的模式也就是這樣子,可以參照自己做一下。

資料

相關文章