React Native的組件開發一直處在一個比較尷尬的處境。在官方未給予相關示例與腳手架的情況下,社區中依然誕生了許許多多的React Native組件。因為缺少示例與規范,很多組件庫僅含有一個index.js
文件。這種基礎的目錄結構也導致了一些顯而易見的問題,例如“如何測試”,“如何預覽”,“如何開發”......本文將為各位提供一種React Native組件開發的示例目錄結構
及相關配置指南
。
示例目錄結構
.
├── src
│ └── index.js
├── test
│ └── index.test.js
├── demo
│ ├── .gitignore
│ ├── .watchmanconfig
│ ├── App.js
│ ├── app.json
│ ├── babel.config.js
│ ├── metro.config.js
│ └── package.json
├── .eslintrc.js
├── babel.config.js
├── README.md
├── .gitignore
└── package.json
目錄結構主要區分為4塊內容根目錄
,src目錄
,test目錄
,demo目錄
。
根目錄包含了eslint配置
,babel配置
,README
, gitignore
, package.json
。其中babel配置
與package.json中
的依賴
定義是為了運行測試用例而存在的。
src目錄包含了當前React Native組件的源碼,是組件開發最主要的目錄。
test目錄包含了當前React Native組件的測試相關代碼。
demo目錄包含了一個獨立的Expo項目,其中App.js
文件是開發組件示例最主要文件,其中會引用src目錄
中提供的組件來進行開發與展示。該目錄的配置詳情會在下文中繼續展開。
為什么用Expo來進行開發與展示?
Expo是一個基于React Native包裹的React Native應用開發框架。許多React Native的開發者對于Expo依然持懷疑態度。不可否認的是用Expo來開發React Native應用確實存在一些問題,例如:
- 引入Expo SDK后,應用體積過大的問題
- 缺乏應用在后臺運行的能力
- ...
但是絕大多數Expo的弊端是我們在組件開發中不會遇到或者可以避開的,那么隨之而來的便是Expo的優點:
- 快速安裝與上手
- 快速在網頁、模擬器、實機上預覽或測試
- 與React Native的無縫兼容性
相信開發過React Native的同學一定會抱怨它沉重的依賴安裝,與繁瑣的調試過程,而Expo正好輕量化了這兩個過程,不僅加速
了我們的組件開發
與預覽
,也在我們的組件目錄中去除了Native端相關的代碼,輕量化
了我們的目錄結構
。
相關配置指南
引入Expo
為組件項目引入Expo可能沒有聽上去這么容易,因為我們在上文的目錄結構中將src目錄
定義成與demo目錄
平行的目錄結構,這就導致了metro
(React Native打包工具)的默認配置將無法正常打包demo目錄
中的React Native代碼。為了解決這個問題,我們就需要手動去調整metro
的配置文件,而metro配置文檔
又以“精簡”著稱,于是配置metro
便成了一個極大的困難點。
準備工作
首先我們需要安裝Expo CLI工具
$ npm install -g expo-cli
在組件庫的根目錄
中運行
$ expo init demo
然后選擇
blank template
managed workflow
你便在demo目錄
中生成了一個可運行的Expo項目, 可以通過運行以下命令來預覽當前的Expo項目
$ cd demo
$ yarn start
配置metro
舊版本metro通常使用rn-cli.config.js
作為配置文件名,而新版本則使用metro.config.js
作為配置文件名。舊版本metro
的配置文件格式也與新版本有較大的差別。本文將重點關注新版本metro
的配置。
在demo目錄
中創建名為metro.config.js
的metro
配置文件,并在Expo的應用配置文件app.json
中添加如下字段用于重置項目根目錄
配置與注入自定義的metro
配置文件
"packagerOpts": {"projectRoots": "","config": "metro.config.js"
}
在metro.config.js
中添加如下內容
const path = require('path');
const blacklist = require('metro-config/src/defaults/blacklist');
const escapeRegexString = require('escape-regex-string');module.exports = {resolver: {blacklistRE: blacklist([new RegExp(`^${escapeRegexString(path.resolve(__dirname, '..', 'node_modules'))}\\/.*$`,),]),providesModuleNodeModules: ['react-native','react','prop-types',],extraNodeModules: {'@babel/runtime': path.resolve(__dirname, 'node_modules/@babel/runtime'),},},projectRoot: path.resolve(__dirname),watchFolders: [path.resolve(__dirname, '..'),],
};
來仔細解析一下上面的配置項
-
providesModuleNodeModules
: 該配置項為當前項目提供額外的providesModule
路徑解析名。providesModule
簡單來說就是一個提供文件路徑別名的手段。例如在一個文件頭部添加如下的注釋,你就可以在項目別處通過import test from 'test'
直接引入該文件。/**
*/
```
在這里我們將注入在src目錄
中被引用的三個庫react-native
, react
, prop-types
,使得src目錄
中的引用能正確被metro
解析。
-
extraNodeModules
: 該配置旨在為當前項目提供額外引入的模塊,配置格式為[{ 模塊名 : 路徑 }]
。我們在這里配置src目錄
中需要的額外模塊,例如運行測試時所需要的@babel/runtime
模塊。 -
blackListRE
: 配置一個正則,打包時忽略掉正則匹配到的路徑。在這里我們將根目錄
中的node_modules
路徑下的所有內容忽略,目的是因為在根目錄
下的node_modules
中會存在與demo目錄
下node_modules
中相同的庫,例如react-native
,react
,prop-types
。這就會使得providesModule
在解析時產生重名,從而導致jest-haste-map
報錯。 -
projectRoot
: 配置項目的根目錄。 -
watchFolders
: 為項目引入除projectRoot
外額外的目錄,在這里我們將上層的根目錄
加入metro
的關注列表。
配置完metro
,即可在App.js
中引入src目錄
中的組件
import React from 'react';
import { StyleSheet, View } from 'react-native';
import Component from '../src';const App = () => (<View style={styles.container}><Component /></View>
);const styles = StyleSheet.create({container: {flex: 1,backgroundColor: '#fff',alignItems: 'center',justifyContent: 'center',},
});export default App;
現在運行yarn start
,就能順利看到你的組件在Expo中展示了。
小結
本文主要提供了一種React Native組件的目錄結構,與“如何在一個React Native組件工程中引入一個含Expo工程的子目錄”的相關配置指南。這里還需要需要說明的一點是,React Native組件的目錄結構可以有千萬種,本文只是提供一種可行的思路供大家參考,如有更好的方案也歡迎交流與學習。本文將重點放在了引入Expo的配置指南上,如需查看該目錄結構的所有文件配置,請轉至Github。
相關
- react-native-component-cli - 快速生成該目錄結構的腳手架工具
- react-native-hsv-color-picker - 基于該目錄結構的組件案例