教你使用Dumi和father-build快速搭建React組件庫

1. 背景

目前我所在業務組是負責後臺管理系統,可是對於使用的組件並無引入第三方庫,全有開發人員本身編寫。可是對於Common Project仍是處於拷貝的方式。而後萌生了對公共組件庫進行管理的想法。這個方式有什麼好處呢?
javascript

  • 可以沉澱組內組件,避免重複造輪子的缺陷。
  • 統一維護組件,使不一樣開發人員遵循同一套使用標準。
  • 本身的UI庫,可以保證系統視覺和交互一致性。
  • 提升產品研發效率,資源重複利用,減小重複開發。
  • 項目統一設計、編碼語言規則,溝通更輕鬆。
  • 專一業務,在視覺要求方面減小花費時間,爭取更好的時間寫業務。

2. 技術選擇(dumi + father-build)

固然,在網上進行查詢,發現不少不少人都作過相似的事情,咱們能夠借鑑不少的經驗。有人是本身編寫的配置。而我在芸芸博客中,篩選了知足個人條件的技術(dumi + father-build)。爲什麼選擇它呢?
css

  • dumi 是螞蟻金服插件化的企業級前端框架,專門爲組件開發場景而生的文檔工具。與father的文檔打包相比,構建編譯速度更快,更友好。
  • father-build屬於father(集文檔與組件打包一體的庫)的一部分。專一於組件打包。

爲何我不選擇本身編寫呢?不只僅是搭建時間的成本,還有後續優化等,目前我沒有自信會比專一於該業務的人作的更好。後續也會去好好學習一下大神是如何實現的,可是迫在眉睫的是我但願完成個人組件庫搭建,所以先偷個小懶了^^。html

3. 文檔庫搭建

@umijs/create-dumi-lib是基於Umi的文檔工具,開箱即用,專一於開發和文檔編寫。運行如下命令,會初始化項目結構。前端

$ npm init
$ npx @umijs/create-dumi-lib
複製代碼

文檔目錄結構


.umirc.ts

是umi項目的配置文件,而dumi是umi在組件庫開發中的一個最佳實踐,可是它本質仍是一個umi插件,所以只要umi的配置,都是能夠在dumi中正常使用的。java

.fatherrc.ts

是father-build的配置文件,組件庫如何編譯以及編譯後產生的類型都須要在這裏使用。node

啓動

運行npm start便可啓動。
react

4. 編寫組件以及引用文檔

編寫一個簡單的實例和docs。git

4.1 配置官網logo(.umirc.ts)

tips: 資源須要放在public目錄下面。例如public/image/xxx.png。否則會訪問不了。es6

// .umirc.ts

import { defineConfig } from 'dumi';
let BaseUrl = ''
export default defineConfig({
    mode: 'site', // site: 站點模式(導航頭 + 左側菜單 + 右側內容)。 doc:文檔
    title: 'Biz Library', // 組件庫名稱
    favicon: BaseUrl + '/images/favicon.ico', 
    logo: BaseUrl + '/images/photos.svg',
    description: '用於Biz Web Dev 前端組件開發。',
});
複製代碼

4.2 編寫組件與組件文檔

component:/src/Dialog/index.tsx

import React, { FC } from 'react';
import './index.less';
interface DialogProps {
  onClick?: React.MouseEventHandler<HTMLElement>;
  type?: 'default' | 'primary' | 'secondary';
  disabled?: boolean;
}
const Dialog: FC<DialogProps> = ({ children, onClick, type = 'dialog' }) => {
  return (
    <div className={'biz_dev_dialog'} onClick={onClick}> {children} </div>
  );
};
export default Dialog;
複製代碼

css:/src/Dialog/index.less

@btn-prefix-cls: ~'biz_dev';

.@{btn-prefix-cls} {
  &_dialog {
    padding: 6px 16px;
    font-size: 12px;
    min-width: 64px;
    color: red;
  }
}
複製代碼

文檔編寫

  • 組件文檔en: docs/component/dialog.md
  • 組件文檔中文: docs/component/dialog.zh-CN.md
  • 包名biz-web-library: 是package.json 中的name
import React from 'react';
import { Dialog } from 'biz-web-library'; // 可經過包名引入,而不是相對路徑
export default () => <Dialog>dialog example</Dialog>;
複製代碼

啓動

運行npm run start,至此本地的開發環境就已經完成啦,你能夠一邊開發一邊調試了。
github

5. CI 測試

測試對於組件庫來講,是必不可少的。在father-build 中,集成了jest用於單元測試。可是對於React組件進行測試還須要進行額外的配置。

jest.config.js

module.exports = {
  setupFiles: ['<rootDir>/testSetUp.js'],
  testEnvironment: 'jsdom', // default: jsdom, 可配置: node
};
複製代碼

testSetUp.js

記得安裝 enzyme-adapter-react-16enzyme

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
複製代碼

編寫測試用例

import React from 'react';
import { render } from 'enzyme';
import Button from '../../src/Button';

describe('test', () => {
	it('test render', () => {
		let Wrapper = render(<Button>case one</Button>);
		expect(true).toBeTruthy();
	})
})
複製代碼

運行npm run test,執行經過。

6. 全量加載 和 按需加載

咱們知道,不少組件庫是將組件統一打包,經過如下方式引入。默認狀況下father-build也是這樣的。

import { componentName } from 'biz-library';
複製代碼

常見的庫(例如antd)是經過配置babel插件實現按需引入。而我但願個人組件庫能夠不經過配置插件,便可實現按需引入。

import componentName from 'biz-library/componentName';
複製代碼

6.1 實現按需加載

.fatherrc.ts

做爲father-build的配置文件,用於配置組件庫被如何編譯和編譯產物的類型。通常設置 esm: 'rollup'就夠用了。但它缺點是會打包在一塊兒,沒法實現按需引入。所以我採用esm: 'babel'

export default {
  target: 'browser',
  esm: 'babel',
  lessInBabelMode: true, // babel 模式下作 less 編譯
  entry: ['src/Button/index.tsx', 'src/Dialog/index.tsx'],
  autoprefixer: {
    browsers: ['ie>9', 'Safari >= 6'],
  },
  pkgs: [
    // 組件依賴構建順序, 例如 a組件依賴於b組件,那麼須要先編譯 b,在編譯a,則 這裏能夠控制組件編譯順序
  ],
};
複製代碼

tsconfig.json

其餘屬性沒什麼好說的, "declaration": true是必須配置的,生成typescript項目中.d.ts後綴的文件。

{
  "compileOnSave": true,
  "compilerOptions": {
    "target": "es6",
    "module": "esnext",
    "lib": ["es2018", "dom"],
    "rootDir": "./",
    "outDir": "es",
    "moduleResolution": "node",
    "importHelpers": true,
    "jsx": "react",
    "esModuleInterop": true,
    "sourceMap": true,
    "baseUrl": "./",
    "strict": true,
    "declaration": true, // 只有declaration設置爲true才能生成.d.ts後綴的文件
    "allowJs": true,
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": false,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "experimentalDecorators": true,
    "skipLibCheck": true,
    "paths": {
      "@/*": ["src/*"],
      "@@/*": ["src/.umi/*"],
      "@@@/*": ["docs/*"]
    },
    "allowSyntheticDefaultImports": true,
    "typeRoots": ["typings", "node_modules/@types"]
  },
  "include": ["src/**/*", "dosc/**/*"],
  "exclude": [
    "node_modules",
    "lib",
    "es",
    "dist",
    "typings",
    "**/__test__",
    "test"
  ]
}
複製代碼

打包發佈至npm

運行npm run build命令,本地打包後,將組件一個個拆分了的,爲咱們按需引入作好了鋪墊。

運行npm run release,將其發佈到npm上,即可以經過npm進行安裝,在項目中進行使用。發佈至npm需注意version: 1.0.0每一次不能相同。

import React from 'react';
import Button from 'biz-web-library/es/Button';
function App() {
  return (<Button>click me</Button>);
}
export default App;
複製代碼

打包路徑修改

從上面的使用方式能夠看出,Button並無在biz-web-library的下面,我其實期待按需引入使用如下方式:

import Button from 'biz-web-library/Button';
複製代碼

通過查詢,終於找到了一個比較優雅的使用方式,Click Me
package.json中配置如下語句,而後直接運行npm publish便可。

"prepublishOnly": "npm run build && cp -r ./es/* . && rm -rf ./es",
"postpublish": "git clean -fd",
"release": "npm publish",
複製代碼

7. 發佈組件官網 到 GitHub Pages

至此,我但願的組件庫編寫已經完成,既能夠全量引入,也能夠按需引入。那麼如何讓別人可以看到咱們的組件庫呢。這裏我使用github pages

github 配置

運行npm run deploy可將文檔部署至github的github pages上。這至關於你組件的官網。請確保github組件倉庫的設置以下:(Path: Settings => Options => GitHub Pages:)

咱們能夠看到生成的地址https://yezizhao.github.io/biz-web-library/,它包含了廠庫的名稱,所以你訪問改地址時,會發現jscss出現404不能訪問了。此時不要慌,說明打包產生的路徑不正確。在.umirc.ts文件中,將let BaseUrl = '/biz-web-library';修改便可。而後在從新運行npm run deploy進行發佈便可。

import { defineConfig } from 'dumi';

let BaseUrl = '/biz-web-library'; // 倉庫的路徑

export default defineConfig({
  // 網站描述配置
  mode: 'site',
  title: 'Biz Library',
  favicon: BaseUrl + '/images/favicon.ico',
  logo: BaseUrl + '/images/photos.svg',
  description: '用於Biz Web Dev 前端組件開發。',

  // 打包路徑配置
  base: BaseUrl,
  publicPath: BaseUrl + '/', // 打包文件時,引入地址生成 publicPath/xxx.js
  outputPath: 'docs-dist',
  exportStatic: {}, // 對每隔路由輸出html
  dynamicImport: {}, // 動態導入

  hash: true, //加hash配置,清除緩存
  manifest: {
    // 內部發布系統規定必須配置
    fileName: 'manifest.json',
  },

  // 多國語順序
  locales: [
    ['en-US', 'English'],
    ['zh-CN', '中文'],
  ],

  // 主題
  theme: {
    '@c-primary': '#16c35f',
  },
});

複製代碼

dumi css丟失

如今,你的網頁能夠訪問了,可是此時的css卻不見了。實際上是由於 md中引入的css是指向構建後的目錄,不能直接指向源碼目錄。我是在package.json中配置sideEffects解決了該問題。

"sideEffects": ["./src/**/*.less"],
複製代碼

78. 結束語

至此,一個簡易的組件庫開發環境和發佈環境就已經搭建完成,可是上面的例子實際上是用的公網的github。而公司內部組件並不該該發佈到公網,所以你還須要搭建一個內部的私有npm。就不進行描述了。

github example實例: github.com/YeziZhao/bi…

相關文章
相關標籤/搜索