通常狀況下,咱們寫 React 項目,用 create-react-app 腳手架開發比較方便,可是若是要寫一個插件的話,用三方腳手架就顯得有點臃腫了,咱們能夠本身配置一個符合咱們開發的簡單工具,本文教你如何一步一步開發一個 React 插件 ,let's start 😊css
工欲善其事,必先利其器,咱們來選型html
爲了方便開發,咱們選用 Typescript 做爲開發語言,能夠即時類型檢查,順便還能裝逼(巨硬大法好),node
注: Typescript 可選的,你也能夠選擇 js 刀耕火種,不過最好仍是用 Typescript 寫吧,畢竟9102年了,騷年 😄react
這裏先用咱們熟悉的 webpack 做爲打包工具(以後會嘗試改爲 rollup 做爲打包工具)webpack
jest 做爲咱們代碼測試的工具,這裏選用 travis ,一個在線持續集成的工具(幫助你打包、構建、運行scripts命令、代碼測試等) 選用 coveralls 能夠根據 travis 代碼測試後生成的代碼覆蓋率生成 badge(Github 好多項目都有的)git
下面咱們來大致組織下目錄結構github
react-yan-progress
├── build // 打包目錄
│ └── YanProgress.min.js
├── src // 源碼
│ ├── index.css
│ └── index.tsx
├── test // 測試文件
│ └── YanProgress.test.js
├── index.d.ts // 聲明文件(ts)
├── jest.config.js // jest 測試配置文件
├── webpack.config.js // webpack 配置文件
├── tsconfig.json // ts 配置文件
├── package.json
├── .travis.yml // travis 配置文件
├── LICENSE
└── README.md
複製代碼
全部的依賴的包以下web
{
"devDependencies": {
"@babel/core": "^7.1.6",
"@babel/preset-env": "^7.1.6",
"@babel/preset-react": "^7.0.0", // for react
"@types/react": "^16.7.18", // 聲明文件
"@types/react-dom": "^16.0.11", // 聲明文件
"babel-loader": "^8.0.4",
"chai": "^4.2.0", // 測試斷言庫
"coveralls": "^3.0.2", // 代碼覆蓋率
"css-loader": "^1.0.1",
"jest": "^23.6.0", // 測試工具
"react": "^16.7.0",
"react-dom": "^16.7.0",
"style-loader": "^0.23.1",
"ts-loader": "^5.3.2", // 解析 ts
"typescript": "^3.2.2", // 解析 ts
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2"
}
}
複製代碼
命令配置以下,詳情 package.json
typescript
{
"scripts": {
"build": "webpack --config webpack.config.js --progress --colors",
"test": "jest ./test/YanProgress.test.js",
"coveralls": "cat ./coverage/lcov.info | coveralls"
},
}
複製代碼
咱們採用 webpack4 ,具體配置請看官網,傳送門npm
const path = require('path');
module.exports = {
mode: "production", // 生產模式
entry: { // 入口
"YanProgress": path.resolve(__dirname, './src/index.tsx')
},
output: { // 出口
path: path.resolve(__dirname, './build'),
filename: '[name].min.js',
publicPath: "./build/",
libraryTarget: 'umd', // 打包方式
library: 'YanProgress', // 導出變量
libraryExport: 'default', // 默認導出
},
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', "@babel/preset-react"]
}
},
{
loader: 'ts-loader', // 解析 ts
}
],
include: path.resolve(__dirname, "./src/"), // 只解析 src 目錄下的文件
},
{
test: /\.css$/,
loader: "style-loader!css-loader?modules&localIdentName=[hash:8]", // css_modules 配置詳情 http://www.ruanyifeng.com/blog/2016/06/css_modules.html
include: path.resolve(__dirname, "./src/"),
}
]
},
resolve: { // 省略文件後綴時,默認按下面的配置取
extensions: ['.ts', '.tsx', '.js'],
},
externals: { // 不把 react 打包進去
react: 'react'
}
};
複製代碼
因爲咱們要在 ts 文件中 引入 css 模塊,可是 ts 不認識,因此咱們須要進行以下配置
在項目的根目錄下新建一個 index.d.ts
ts 聲明文件
declare module '*.css';
複製代碼
這裏就是與日常的開發組件同樣,舉個例子
// jsx
import React from 'react';
class YanProgress extends React.Component{
render() {
return (
<div> 騷年,寫代碼快樂嗎,看我幹嗎 😄,趕快滾去寫代碼啊,別忘了點個 star 😂 </div>
);
}
}
export default YanProgress; // 記得導出啊,騷年
複製代碼
你能夠直接看我寫好的代碼(而後 ctrl+c,ctrl+v),源碼在這裏,點我
webpack4 默認會壓縮代碼,so 咱們直接執行剛纔 package.json 配置好的 scripts 的命令
$ yarn
$ yarn run build
複製代碼
單元測試
能夠在 test
目錄下新建一個 xxx.test.js
的測試文件,寫好測試用例(這裏使用的是 chai 斷言庫的 expect 風格),執行以下命令
$ yarn run test
複製代碼
包測試
若是你也想以 npm 包的形式引入(import YanProgress from 'react-yan-progress'
),測試的話,能夠執行以下命令
在你的項目根目錄下,打開終端運行以下命令,創建連接
$ yarn link
複製代碼
在你要測試的 demo 項目根目錄下,執行以下,而後你就能夠這樣使用了 import YanProgress from 'react-yan-progress'
$ yarn link react-yan-progress
複製代碼
這裏用到比較方便簡單的 travis 在線測試工具,和測試代碼覆蓋率工具 coveralls,網址以下:
持續集成 travis-ci.org
代碼覆蓋率 coveralls.io
註冊使用過程就略過了,畢竟已經有不少教程了(面向谷歌編程 😂)
在項目根目錄下新建一個 .travis.yml
文件,配置以下
language: node_js # 運行環境
node_js:
- "10.6.0" # 版本
branches:
only:
- master # 只有主支能夠
before_install:
- export TZ='Asia/Shanghai' # 若是你的項目裏涉及到時間處理,這裏須要設置時區
install: yarn install # 安裝 npm 包
script: # 執行命令
- yarn run build # 打包
- yarn run test # 測試
after_success: # 成功以後執行以下命令
- yarn run coveralls # 測試代碼覆蓋率
複製代碼
註冊 npm 帳號,註冊過程略
注意以前,先去 npm 官網找一下,你的包名有木有被搶先佔用了
執行以下命令進行發佈
$ npm publish
複製代碼
升級包
執行以下命令(x.x.x -> major.minor.patch)
$ npm version patch
複製代碼
擁抱開源,這樣才能讓社區,乃至行業發展更有動力
注:例如,你的 star 是對我最大的鼓勵,是支持我繼續開源的動力
Github
探索👏 歡迎你們一塊兒和我搞 ji(Github)😊