手摸手,打造属于本身的 React 组件库01 — 基础篇

第一部分 - 基础篇:从 0 到 1,还原一个后台项目javascript

原文连接css

引言

2020年,做为一名普通前端打字员,我平时工做的主要目标仍是使用 React 构建应用程序。去年一直想创建一个属于本身的 NPM 库,用于沉淀本身的业务组件、Hooks,可是因为不少概念都不是很了解的缘故,又感受这个目标有点高不可攀。前端

可是其实只要明白一些原理和细节以后,构建本身的 NPM 库实际上是一件很简单的事情。不只能够拓宽视野,还能够将本身在多个项目中反复使用的某些相同的组件编译到一个组件库中,推广给其余小伙伴使用,贡献开源,岂不美哉。java

教程部分

本篇文章,是这个系列的第一篇:基于 React 和 Antd,从 0 到 1,还原一个后台项目node

技术栈

让咱们看看在 2020 年,一个普通的后台项目,须要的技术栈有哪些:react

  • React:最流行的 UI 层 JavaScript 库
  • Antd:西湖区最流行的 UI 设计语言
  • Create React App:官方 Cli 脚手架
  • React-Router:处理路由
  • TypeScript:9012 年成长最快的前端编程语言,提供了类型系统对 ES6 的支持
  • eslint & prettier & husky:整合代码规范,统一编码风格。
  • less:参考 Antd 文档,配合 react-app-rewired 等库让咱们的构建工具支持 less。

项目准备

具体实现,能够参考这个:Demo 项目git

预览地址:jokingzhang.github.io/dantd-demo/es6

使用 React + TypeScript 开始项目

此处首先肯定下,咱们已经安装了 npm 模块,没有安装的童鞋能够去 Node 官网 下载一个安装包安装一下,而后你就有 npm 了😑。github

执行下面的命令,初始化项目:typescript

sudo npm i -g npx
npx create-react-app my-app --template typescript
cd my-app
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
npm start
复制代码

这个时候,应该能够看到一个经典的初始化页面了~

安装 Antd

npm install antd --save
复制代码

安装 React Router

npm install --save react-router-dom @types/react-router-dom
复制代码

使用 eslint & prettier & husky 整合代码规范,统一编码风格

安装依赖
npm install -D eslint eslint-config-prettier eslint-config-react-app eslint-plugin-flowtype eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-prettier eslint-plugin-react eslint-plugin-react-hooks lint-staged prettier husky
复制代码

依赖安装好以后,就能够为项目增长一些配置文件了

tsconfig.json

tsconfig.json 文件中指定了用来编译这个项目的根文件和编译选项。这是当前项目所用到的配置文件:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "es6",
      "dom"
    ],
    "downlevelIteration": true,
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "sourceMap": true,
    "baseUrl": "./src",
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "node"
  },
  "exclude": [
    "node_modules"
  ],
  "include": [
    "src"
  ]
}

复制代码
.eslintrc

.eslintrc 文件中,容许你指定你想要支持的 JavaScript 语言选项。这是当前项目所用到的配置文件:

{
    "extends": "react-app",
    "plugins": ["prettier"],
    "rules": {
      "prettier/prettier": "error",
      "no-unused-vars": "off",
      "@typescript-eslint/no-unused-vars": ["error", {
        "vars": "all",
        "args": "after-used",
        "ignoreRestSiblings": false
      }]
    }
}
  
复制代码
.eslintignore

你能够经过在项目根目录建立一个 .eslintignore 文件告诉 ESLint 去忽略特定的文件和目录。.eslintignore 文件是一个纯文本文件,其中的每一行都是一个 glob 模式代表哪些路径应该忽略检测。

node_modules/*
复制代码
.prettierrc.js

prettierrc 的配置文件,打造适合大家团队的代码配置

module.exports = {
  singleQuote: true,
  trailingComma: 'all',
  printWidth: 100,
  proseWrap: 'never',
  overrides: [
    {
      files: '.prettierrc',
      options: {
        parser: 'json',
      },
    },
  ],
};
  
复制代码
.vscode/settings.json

若是你是使用 Visual Studio Code 来开发项目的话,这个配置文件就能够方便的统一团队的编辑器配置,解决项目中,缩进是「2个空格」仍是「4个空格」的问题。

{
  "editor.tabSize": 2,
  "eslint.autoFixOnSave": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    { "language": "typescript", "autoFix": true },
    { "language": "typescriptreact", "autoFix": true }
  ],
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}
复制代码
.env

当咱们搜索 create-react-app 是如何快速解决 alias 的问题时,Dan 给出的答案是添加 .env 这个文件:

NODE_PATH=src
复制代码

到这里,就整理完了全部须要的配置文件

使用 Less

更加详细的解析,请参考 Antd 的文档

安装下面依赖:

npm i -D react-app-rewired customize-cra babel-plugin-import less less-loader
复制代码
修改 package.json
/* package.json */
"scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test",
+   "test": "react-app-rewired test",
}
复制代码
config-overrides.js

而后在项目根目录建立一个 config-overrides.js 用于修改默认配置。

const { override, fixBabelImports, addLessLoader } = require('customize-cra');

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: true,
  }),
  addLessLoader({
    javascriptEnabled: true,
  }),
);

复制代码

到此,咱们就能够在项目中,愉快的使用 less 了~

项目结构

此时,使用编辑器打开项目,咱们能够看到以下的 src 目录结构:

├── src
|  ├── App.css
|  ├── App.test.tsx
|  ├── App.tsx
|  ├── index.css
|  ├── index.tsx
|  ├── logo.svg
|  ├── react-app-env.d.ts
|  ├── serviceWorker.ts
|  └── setupTests.ts
复制代码

这是脚手架为咱们准备的初始目录结构。接下来,咱们须要在这个基础上,进行一些改造。以一个最为简单的 EmptyLine 组件为例子,看看咱们须要增长哪些文件。

处理路由

首先,增长两个文件夹 , pages 用来存放路由相关的组件,以及components 用来存放通用组件。
此处不作赘述,感兴趣的小伙伴能够看下 demo 的实现

此时,代码结构以下:

├── src
|  ├── App.less
|  ├── App.test.tsx
|  ├── App.tsx
|  ├── components
|  |  ├── empty-line
|  |  |  ├── EmptyLine.tsx
|  |  |  ├── demo.tsx
|  |  |  ├── index.tsx
|  |  |  └── style
|  |  └── index.tsx
|  ├── config.tsx
|  ├── index.css
|  ├── index.tsx
|  ├── logo.svg
|  ├── pages
|  |  ├── Component
|  |  |  ├── index.tsx
|  |  |  └── style.less
|  |  ├── Home
|  |  |  ├── index.tsx
|  |  |  └── style.less
|  |  └── NotFound
|  |     └── index.tsx
|  ├── react-app-env.d.ts
|  ├── serviceWorker.ts
|  └── setupTests.ts
复制代码

pages 下面的目录结构比较容易理解,只存放了组件,以及样式文件。

components 下的目录结构,主要参考了 Antd 的源码实现。这样写的有以下好处:

  • 分离了样式组件,结构清晰
  • 代码结构更加清晰,便于以后组件的导出
  • 因为咱们使用 babel-plugin-import 来进行按需加载 Antd,当咱们想使用 ES module 的方式引入组件的时候,它会对咱们 es 目录下的文件有所要求:

下面摘自 babel-plugin-import 的文档:

  • { "libraryName": "antd" }
import { Button } from 'antd';
ReactDOM.render(<Button>xxxx</Button>);

      ↓ ↓ ↓ ↓ ↓ ↓

var _button = require('antd/lib/button');
ReactDOM.render(<_button>xxxx</_button>);
复制代码
  • { "libraryName": "antd", style: "css" }
import { Button } from 'antd';
ReactDOM.render(<Button>xxxx</Button>);

      ↓ ↓ ↓ ↓ ↓ ↓

var _button = require('antd/lib/button');
require('antd/lib/button/style/css');
ReactDOM.render(<_button>xxxx</_button>);
复制代码
  • { "libraryName": "antd", style: true }
import { Button } from 'antd';
ReactDOM.render(<Button>xxxx</Button>);

      ↓ ↓ ↓ ↓ ↓ ↓

var _button = require('antd/lib/button');
require('antd/lib/button/style');
ReactDOM.render(<_button>xxxx</_button>);
复制代码

因此,不论以后时使用 commonjs 的方式打包,仍是使用 es 的方式打包,组件的目录结构最好和 Antd 的组件目录结构保持一致,不然 babel-plugin-import 这个插件会找不到对应的文件所在。

增长第一个组件

如今,咱们能够开始写咱们的第一个组件了,<EmptyLine />:产生一个空行,而且能够根据 props 改变高度。

src/index.tsx
export { default as EmptyLine } from './empty-line';
复制代码
src/empty-line/index.tsx
import './style/index.less';
import EmptyLine from './EmptyLine';

export default EmptyLine;
复制代码
src/empty-line/EmptyLine.tsx
import React from 'react';
import './style/index.less';

export interface IEmptyLineProps {
  height?: number;
}

const EmptyLine = ({ height = 20 }: IEmptyLineProps) => {
  return <div className="empty-line" style={{ height }} />;
};

export default EmptyLine;
复制代码
src/empty-line/style/index.less
.empty-line {
    width: 100%;
    height: 20px;
}
复制代码
src/empty-line/demo.tsx
import React from 'react';
import EmptyLine from './EmptyLine';

const demo = () => {
  return (
    <div>
      <h3>组件名称:空行(EmptyLine)</h3>
      <p>自定义组件,默认高度 20 ,宽度 100%</p>
      <p>第一行文字</p>
      <EmptyLine />
      <p>第二行文字</p>
    </div>
  );
};

export default demo;
复制代码

到这里,组件就完成了,这是:预览地址

image

结束语

咱们已经从头开始建立了 React 组件库!在接下来的章节中,还会和你们讨论测试,和打包的话题,敬请期待吧~

相关文章
相关标签/搜索