基於 CRA 快速搭建 React 組件庫

本章篇幅較長,尬很少說,造輪子開始~~css


1. 初始化項目 create-react-app + TS

npx create-react-app my-component-library --template typescript前端

參考:create-react-app.dev/docs/adding…node

2. 支持編譯 Sass

CRA 默認不支持 Sass 預處理器,須要安裝 node-sassreact

npm install node-sass --savegit

支持 sass 以後,接下來能夠爲組件庫添加一些樣式管理,好比定義基礎組件庫色板變量,github

// 基礎色板
$blue: #0d6efd !default;
$indigo: #6610f2 !default;
$purple: #6f42c1 !default;
$pink: #d63384 !default;
$red: #dc3545 !default;
$orange: #fd7e14 !default;
$yellow: #fadb14 !default;
$green: #52c41a !default;
$teal: #20c997 !default;
$cyan: #17a2b8 !default;
複製代碼

添加 reset 全局樣式,可參考 normalize.css 庫,它提供了跨瀏覽器的高度一致性。typescript

3. 編寫 Button 組件

下面簡單列舉開發組件幾個經常使用的點,至於怎麼開發出一個合格好用的組件,還須要日積月累、慢慢摸索~npm

  1. 組件 className 屬性通常支持 btn, btn-lg, btn-primary 等不一樣樣式管理,推薦使用 classnames 插件進行樣式名管理, 配置 classNames :

npm i classnames --save npm install --save @types/classnamesjson

  1. 經過 Button.defaultProps 爲添加 props 賦默認值windows

  2. ButtonHTMLAttributesbutton 全部原生屬性類型,能夠經過定義自定義屬性類型和 button 全部原生屬性類型,讓用戶使用組件時得到更好的屬性類型提示。

Button 組件參考實現 ⬇️

// Button.tsx
import React, { FC, ButtonHTMLAttributes, AnchorHTMLAttributes } from "react";
import classNames from "classnames";

export type ButtonSize = "lg" | "sm";

export type ButtonType = "primary" | "default" | "danger" | "link";

interface BaseButtonProps {
  className?: string;
  /**設置 Button 的禁用 */
  disabled?: boolean;
  /**設置 Button 的尺寸 */
  size?: ButtonSize;
  /**設置 Button 的類型 */
  btnType?: ButtonType;
  children: React.ReactNode;
  href?: string;
}
// ButtonHTMLAttributes 是button全部原生屬性類型
type NativeButtonProps = BaseButtonProps & ButtonHTMLAttributes<HTMLElement>;
// a 連接原生屬性
type AnchorButtonProps = BaseButtonProps & AnchorHTMLAttributes<HTMLElement>;
// TS Utility Types : Partial 屬性可選,並非都有的
export type ButtonProps = Partial<NativeButtonProps & AnchorButtonProps>;

export const Button: FC<ButtonProps> = (props) => {
  const {
    btnType,
    className, // 用戶自定義className
    disabled,
    size,
    children,
    href,
    ...restProps // 包含了其餘的全部原生屬性
  } = props;

  // 配置 classNames : btn, btn-lg, btn-primary
  // disable說明:button 默認支持disabled屬性;但 a 連接disable屬性就要經過樣式來控制了,因此添加到classname裏
  const classes = classNames("btn", className, {
    [`btn-${btnType}`]: btnType,
    [`btn-${size}`]: size,
    disabled: btnType === "link" && disabled,
  });

  // button 包括 link類型和其餘類型
  if (btnType === "link" && href) {
    return (
      <a className={classes} href={href} {...restProps}> {children} </a>
    );
  } else {
    return (
      <button className={classes} disabled={disabled} {...restProps}> {children} </button>
    );
  }
};

Button.defaultProps = {
  disabled: false,
  btnType: "default",
};

export default Button;
複製代碼

4. 使用 Jest 測試框架

Create React App 中,Jest 已經可以開箱即用,且包含許多實用的默認配置。

從 package.json 中能夠看到 CRA 已內置了相關測試包:

{
  "scripts": {
    "test": "react-scripts test"
  },
  "dependencies": {
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/user-event": "^12.1.10",
    "@testing-library/react": "^11.2.5"
  }
}
複製代碼

1. 編寫測試用例

// Button.test.tsx
import React from "react";
import { render } from "@testing-library/react";
import Button from "./Button";

test("my test", () => {
  const wrapper = render(<Button>按鈕</Button>);
  const ele = wrapper.queryByText("按鈕");
  expect(ele).toBeTruthy();
});
複製代碼

2. 執行 npm run test

此時會先運行 setupTests.ts 文件,而後跑一遍測試用例。

參考:

create-react-app.dev/docs/runnin…

www.jestjs.cn/

testing-library.com/

5. 組件庫文檔開發與部署

本文使用文檔生成工具 docz 進行開發。docz Demo 參考 create-react-app-ts Doc

1. 安裝 npm install docz

2. 配置 scripts 腳本

{
  "scripts": {
    "docz:dev": "docz dev",
    "docz:build": "docz build",
    "docz:serve": "docz build && docz serve"
  }
}
複製代碼

3. 爲 Button 組件添加文檔說明

新建 Button.mdx 文件(按照模板規範編輯便可) 注意須要引入全局樣式 index.scss.

---
name: Button
menu: Components ---

import { Playground, Props } from "docz";
import { Button } from "./Button";
import "../../style/index.scss";

# Button

## Properties

<Props of={Button} />

## Basic usage

<Playground>
  <Button btnType="primary"> primary button </Button>
</Playground>

## Using different kinds

<Playground>
  <Button btnType="danger"> danger button </Button>
  <Button btnType="link" href="https://google.com">
 link button </Button> </Playground> 複製代碼

4. 添加配置文件 doczrc.js

主要用來支持編譯 TS

// doczrc.js
export default {
  typescript: true,
  files: ["./src/**/*.mdx"], // 指定生成文檔的文件
};
複製代碼

參考:docz Project Configuration

5. 編譯 SCSS

此時運行的本地組件庫文檔無法正常展現樣式,須要配置編譯 SCSS 文件,參考 Using docz with CSS Preprocessors

  • npm install --save gatsby-plugin-sass
  • 配置 gatsby-config.js 文件
//gatsby-config.js
module.exports = {
  plugins: ["gatsby-plugin-sass"],
};
複製代碼

6. 本地預覽與打包

執行 npm run docz:dev,此時本地文檔就能夠正常跑起來啦 (沒有作美觀調整,組件庫樣式簡單粗暴)

通常本地運行報錯以後,會存在緩存文件,須要刪除本地.docz 文件夾,從新運行 npm run docz:dev 便可。

下面是代碼目錄結構

接下來就是如何將打包後的組件庫文檔,部署到遠端服務器,並進行在線瀏覽

7. 使用 Netlify 一鍵部署

本項目採用 Netlify 一個能夠用來作靜態網站的持續集成與持續部署的工具。只需設置一次,之後每次咱們提交代碼的時候,Netlify 會自動幫咱們部署最新的代碼。

  • 首先執行 npm run docz:build,生成打包後的文檔默認在 .docz/dist 目錄下,提交代碼。
  • 而後就是 Netlify 的相關配置,主要就是配置須要部署的代碼 git 地址、部署前自動執行的腳本 npm run docz:build 以及須要配置待部署的文件目錄位置 .docz/dist

Netlify 的部署配置工做是十分簡單的,基本按照提示就能夠徹底配置好。能夠參考這篇文章使用 netlify 部署你的前端應用

Deploy log 日誌能夠很清晰的看出 Netlify 的構建過程 :

Installing dependencies -> Build command from Netlify app --> Deploy site --> Build script success

一鍵 deploy 成功後,直接點擊域名連接便可愉快的訪問咱們的組件庫在線文檔啦!傳送門 🚪

6. 組件庫打包

部署完組件庫在線文檔後,接下來就是如何將咱們的組件庫進行打包與發佈了,這裏主要使用 TS 進行編譯配置。

1. 建立組件庫入口文件

// index.tsx
export { default as Button } from "./components/Button";
複製代碼

2. 編寫 tsconfig 配置文件及打包

  • 新建 tsconfig.build.json 文件進行 TS 編譯配置文件
  • 配置 script 腳本: "build-ts":"tsc -p tsconfig.build.json"
  • 執行 npm run build-ts 進行打包
{
  "compilerOptions": {
    "outDir": "dist",
    "module": "esnext",
    "target": "es5",
    "declaration": true,
    "jsx": "react",
    "moduleResolution": "Node",
    "allowSyntheticDefaultImports": true
  },
  "include": ["src"],
  "exclude": ["src/**/*.test.tsx", "src/setupTests.ts"]
}
複製代碼

發現此時 scss 文件並無被打包,接下來使用 node-sass 進行編譯

  • 添加 script 腳本:"build-css": "node-sass ./src/styles/index.scss ./dist/index.css"

  • 編譯前須要刪除老的 dist 文件夾。 Linux 下可使用 rm -rf dist,但不兼容 windows。CRA 已經內置了 rimraf 插件,增長刪除 script 腳本 "clean": "rimraf ./dist" , 參考以下:

{
  "scripts": {
    "start": "react-scripts start",
    "build": "npm run clean && npm run build-ts && npm run build-css", // 順序執行
    "clean": "rimraf ./dist",
    "build-ts": "tsc -p tsconfig.build.json",
    "build-css": "node-sass ./src/style/index.scss ./dist/index.css"
  }
}
複製代碼

執行 npm run build, 控制檯能夠看到三條命令依次執行。

打包後目錄結構以下

3. 配置組件庫入口文件

  • package.json 中新增字段
{
  "main": "dist/index.js",
  "module": "dist/index.js",
  "types": "dist/index.d.ts"
}
複製代碼

7. 使用 npm link 本地測試組件庫

在本地開發 npm 模塊的時候,咱們可使用 npm link 命令,將 npm 模塊連接到對應的運行項目中去,方便地對模塊進行調試和測試

  1. 本地新建一個 demo 項目 test-component-library 用於測試組件庫的使用
  2. 當前組件庫 my-component-library 下(須要被 link 的包)執行:
npm link
// success : /usr/local/lib/node_modules/my-component-library -> /Users/當前組件庫項目路徑/my-component-library
// 全局 node_modulus 下會建立一個軟連接 ---> 連接到當前組件庫項目路徑
複製代碼
  1. demo 項目(須要 link 本地包的測試項目)下執行:
npm link my-component-library
// success : /Users/當前測試項目路徑/test-component-library/node_modules/my-component-library -> /usr/local/lib/node_modules/my-component-library -> /Users/liyang86/當前組件庫項目路徑/my-component-library

// 本地 test 項目中 node_modules/my-component-library 建立軟連接 ---> 連接到全局環境 node_modules/my-component-library 做爲中轉 ---> 又連接到當前組件庫項目路徑
複製代碼

此時 test 項目 node_modules 中已有 my-component-library 文件夾了!而且修改組件庫內容時,demo 項目中 link 的組件包也會實時更新哦。

  1. 引入組件及全局樣式
// test-component-library 下
import { Button } from "my-component-library";
import "my-component-library/dist/index.css";

<Button btnType="primary" size="lg"> Button </Button>;
複製代碼

運行一下測試項目,Button 組件已經能夠正常使用啦。

8. 發佈 npm

本地測試組件庫經過後,接下來就是最後一步,發佈組件庫到 npm!

1. 配置 package.json 經常使用字段

  • description: "React Component Lib",
  • author: "my",
  • private: false,
  • license: "MIT",
  • keywords: [ "Component","UI","React"],
  • homepage: "github.com/sdyz/my-com…",
  • repository: { "type": "git", "url": "github.com/sdyz/my-com…" },
  • files: ["dist"], dist 文件夾下內容即待發布文件

即便不配置 ignore 或者 files 也會被髮布的文件:package.json、README.md、changelog.md、license

2. 提交發布前檢查

經過命令行鉤子函數的方式進行驗證,包括測試用例驗證和 lint 代碼格式檢查

  • ESLint 檢查
    • --ext 選項 指定 ESLint 在指定的目錄下查找 JavaScript 文件時要使用的文件擴展名
    • 配置腳本 "lint": "eslint --ext js,ts,tsx src --max-warnings 5"
    • 執行 npm run lint 進行測試
  • Test 檢查
    • npm run test 方式會 watch,但不會返回結果,下面進行改進 參考:create-react-app.dev/docs/runnin…
    • cross-env 跨平臺設置環境變量 npm install --save-dev cross-env
    • 配置腳本 "test:nowatch": "cross-env CI=true react-scripts test",
    • 執行 npm run test:nowatch 測試成功。假如測試用例不經過,會中斷退出運行。
  • 增長代碼提交校驗工具 Husky
"husky": {
    "hooks": {
      "pre-commit": "npm run test:nowatch && npm run lint"
    }
  },
複製代碼

3. 配置 publish 腳本

  • prepublish 發佈前的鉤子函數
  • 配置腳本 "prepublish": "npm run test:nowatch && npm run lint && npm run build"

4. 發佈

  • npm whoami 檢測是否登陸 npm
  • npm adduser 未登陸的話進行登陸/註冊
  • npm config lsnrm ls 查看當前 registry 信息(須要使用默認的 npm 源)
  • 執行 npm publish 成功發佈!

9. 組件庫使用

npm install @sdyz/my-component-library

import { Button } from "@sdyz/my-component-library";
import "@sdyz/my-component-library/dist/index.css";

<Button btnType="primary" size="lg"> Button </Button>;
複製代碼

大功告成!!撒花 ✿✿ ヽ(°▽°)ノ ✿ ✌️✌️✌️

參考

JSDoc 註釋規範

組件庫包地址

相關文章
相關標籤/搜索