本章篇幅较长,尬很少说,造轮子开始~~css
npx create-react-app my-component-library --template typescript
前端
参考:create-react-app.dev/docs/adding…node
CRA 默认不支持 Sass 预处理器,须要安装 node-sass
,react
npm install node-sass --save
git
支持 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
下面简单列举开发组件几个经常使用的点,至于怎么开发出一个合格好用的组件,还须要日积月累、慢慢摸索~npm
className
属性通常支持 btn, btn-lg, btn-primary
等不一样样式管理,推荐使用 classnames
插件进行样式名管理, 配置 classNames :npm i classnames --save
npm install --save @types/classnames
json
经过 Button.defaultProps
为添加 props
赋默认值windows
ButtonHTMLAttributes
是 button
全部原生属性类型,能够经过定义自定义属性类型和 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;
复制代码
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"
}
}
复制代码
// 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();
});
复制代码
npm run test
此时会先运行 setupTests.ts 文件,而后跑一遍测试用例。
参考:
create-react-app.dev/docs/runnin…
本文使用文档生成工具 docz 进行开发。docz Demo 参考 create-react-app-ts Doc。
{
"scripts": {
"docz:dev": "docz dev",
"docz:build": "docz build",
"docz:serve": "docz build && docz serve"
}
}
复制代码
新建 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> 复制代码
主要用来支持编译 TS
// doczrc.js
export default {
typescript: true,
files: ["./src/**/*.mdx"], // 指定生成文档的文件
};
复制代码
此时运行的本地组件库文档无法正常展现样式,须要配置编译 SCSS 文件,参考 Using docz with CSS Preprocessors
npm install --save gatsby-plugin-sass
gatsby-config.js
文件//gatsby-config.js
module.exports = {
plugins: ["gatsby-plugin-sass"],
};
复制代码
执行 npm run docz:dev
,此时本地文档就能够正常跑起来啦 (没有作美观调整,组件库样式简单粗暴)
通常本地运行报错以后,会存在缓存文件,须要删除本地.docz 文件夹,从新运行 npm run docz:dev
便可。
下面是代码目录结构
接下来就是如何将打包后的组件库文档,部署到远端服务器,并进行在线浏览
本项目采用 Netlify 一个能够用来作静态网站的持续集成与持续部署的工具。只需设置一次,之后每次咱们提交代码的时候,Netlify 会自动帮咱们部署最新的代码。
npm run docz:build
,生成打包后的文档默认在 .docz/dist
目录下,提交代码。npm run docz:build
以及须要配置待部署的文件目录位置 .docz/dist
等Netlify 的部署配置工做是十分简单的,基本按照提示就能够彻底配置好。能够参考这篇文章使用 netlify 部署你的前端应用。
Deploy log 日志能够很清晰的看出 Netlify 的构建过程 :
Installing dependencies -> Build command from Netlify app --> Deploy site --> Build script success
一键 deploy 成功后,直接点击域名连接便可愉快的访问咱们的组件库在线文档啦!传送门 🚪
部署完组件库在线文档后,接下来就是如何将咱们的组件库进行打包与发布了,这里主要使用 TS 进行编译配置。
// index.tsx
export { default as Button } from "./components/Button";
复制代码
tsconfig
配置文件及打包"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
, 控制台能够看到三条命令依次执行。
打包后目录结构以下
{
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts"
}
复制代码
在本地开发 npm 模块的时候,咱们可使用 npm link 命令,将 npm 模块连接到对应的运行项目中去,方便地对模块进行调试和测试
npm link
// success : /usr/local/lib/node_modules/my-component-library -> /Users/当前组件库项目路径/my-component-library
// 全局 node_modulus 下会建立一个软连接 ---> 连接到当前组件库项目路径
复制代码
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 的组件包也会实时更新哦。
// test-component-library 下
import { Button } from "my-component-library";
import "my-component-library/dist/index.css";
<Button btnType="primary" size="lg"> Button </Button>;
复制代码
运行一下测试项目,Button
组件已经能够正常使用啦。
本地测试组件库经过后,接下来就是最后一步,发布组件库到 npm!
package.json
经常使用字段即便不配置 ignore 或者 files 也会被发布的文件:package.json、README.md、changelog.md、license
经过命令行钩子函数的方式进行验证,包括测试用例验证和 lint 代码格式检查
--ext
选项 指定 ESLint 在指定的目录下查找 JavaScript 文件时要使用的文件扩展名"lint": "eslint --ext js,ts,tsx src --max-warnings 5"
npm run lint
进行测试npm run test
方式会 watch,但不会返回结果,下面进行改进 参考:create-react-app.dev/docs/runnin…npm install --save-dev cross-env
"test:nowatch": "cross-env CI=true react-scripts test",
npm run test:nowatch
测试成功。假如测试用例不经过,会中断退出运行。npm install husky --save-dev
"husky": {
"hooks": {
"pre-commit": "npm run test:nowatch && npm run lint"
}
},
复制代码
"prepublish": "npm run test:nowatch && npm run lint && npm run build"
npm whoami
检测是否登陆 npmnpm adduser
未登陆的话进行登陆/注册npm config ls
或 nrm ls
查看当前 registry 信息(须要使用默认的 npm 源)npm publish
成功发布!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>;
复制代码
大功告成!!撒花 ✿✿ ヽ(°▽°)ノ ✿ ✌️✌️✌️