npm如何发布自己的组件库

1,686 阅读7分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

为什么要开发组件库?

  • 组件库可以与业务代码完全分开
  • 可以独立进行开发,方便维护和拓展
  • 组件具有独立性,组件之间可自由组合
  • 方排查问题,某个组件出现问题,直接对组件进行处理
  • 可以让多个项目重复又使用,提高前端开发效率和可维护性

nwb 是什么?

既然组件库有这么多优势,那么如何开发一个组件库? 答案是:nwb, nwb是一个非常优秀的组件库开发工具:

  • nwb用来开发组件库 (常用的组件库比如Bootstrap,AntDesign)
  • 即装即用,无需配置, 简单易上手
  • 可以直接发布到npm/cnpm
  • 可独立进行单元测试,保证代码健壮性

官方文档: insin/nwb

nwb安装

安装之前的准备

  • 电脑装有:npm / cnpm / yarn
// cnpm 安装: cnpm是企业级npm私服,淘宝团队做了国内完整npm镜像叫cnpm,每次10分钟跟npm官网同步一次, 
// npm服务器在国外,cnpm服务器在国内,cnpm替代npm安装可提高安装速度

npm install -g cnpm --registry=https://registry.npm.taobao.org

//yarn 安装:Yarn是facebook发布的一款取代npm的包管理工具

npm install -g yarn  或者  brew install yarn

开始安装

  • 全局安装nwb, 使用npm或者cnpm
npm install -g nwb  //全局安装nwb
  • npm失败或者非常慢, 可以尝试使用cnpm安装,cnpm速度比较快
cnpm install -g nwb  //全局安装nwb

使用nwb创建组件

  • nwb创建一个名字叫nwb-demo的项目,名字自己随意取, 这里取名nwb-demo只是做demo
nwb new react-component nwb-demo
  • 之后问关于配置问题
? Do you want to create an ES modules build for use by compatible bundlers? (Y/n)
// 回复Y ,询问是否创建 ES modules 

Do you want to create a UMD build for global usage via <script> tag? (y/N)
// 回复Y,创建 UMD

? Which global variable should the UMD build set? ()
//回复ReactLoadingButton, 一般用React社区约定模块名称TitleCase版本,ReactLoadingButton
  • 之后自动创建文件 , 其中着重关注 demo src /index.js tests neb.config.js
nwb-demo
  .gitignore
  .travis.yml
  CONTRIBUTING.md
  nwb.config.js  //调整拓展nwb提供的默认配置
  package.json
  README.md
  demo/         //demo文件夹,协助开发组件模块,不会打包进npm包
    src/
      index.js
  node_modules/
  src/
    index.js    //构建自己的react组件模块
  tests/        //组件测试模块
    *.eslintrc*
    index-test.js

创建单个组件

  • 进入刚刚创建的 nwb-demo 文件
cd nwb-demo 
  • 在nwb-demo 项目里有一个demo( ./demo/src/index.js )文件,这个文件可以用来创建演示应用的,(你可以把他认为是一个父组件)你的组件可以在这个demo中测试,如果不需要可以放心的删除 (以下创建一个Button为例说明)
//.demo/src/index.js
import React, {Component} from 'react'
import {render} from 'react-dom'
import Button from '../../src/index';

class Demo extends Component {
  handleClick =  ()=> {
    console.log("已点击");
  }
  render() {
    return (
      <div>
        <Button 
          onClick = {()=>{this.handleClick()}} 
          disabled = {false}
        >
          登陆
        </Button>
        <Button disabled = {true} >禁用</Button>
        <Button />
      </div>
    )
  }
}
render(<Demo/>, document.querySelector('#demo'))

安装classnames: 类选择器,react官方推荐库,用来动态判断不同状态class(类名)

官方文档: JedWatson/classnames

  • 安装方式:
npm install classnames --save 
  • 还有一个./src/index.js文件,这个是自己开发组件的文件(你可以把他认为是一个子组件
//./src/index.js
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import CX from 'classnames';
import './index.css';

class Button extends Component {
  render() {
    const { children, onClick, disabled, ...props} = this.props;
    return (
      <span
        className = {CX({
          btn:true,
          "btn-disabled": disabled === true ,
        })}
				{...props}
      >
        <span className = 'btn-content'>
          {children}
        </span>
      </span>
    )
  }
}

Button.propTypes = {
  children: PropTypes.string,
  onClick: PropTypes.func,
  disabled: PropTypes.bool,
}
Button.defaultProps = {
  children:"Button",
  onClick: () => {return null},
  disabled : false,
}
export default Button

//./src/index.css 
.btn{
    display: flex;
    align-self: center;
    justify-content: center;
    width:56px;
    height:32px;
    border-radius:4px;
    background:rgba(46,170,220,1);
}
.btn:hover{
    background:rgba(7,156,205,1);
    cursor: pointer;
}

.btn:active{
    background:rgba(2,141,190,1);
    opacity: 0.5;
}

.btn-disabled{
    background:rgba(0,0,0,0.4);
    pointer-events: none;
}

.btn-content{
    font-size:12px;
    font-weight:600;
    color:rgba(255,255,255,1);
    line-height:32px;
}
  • 运行单个组件
npm start
//Compiled successfully in 2854 ms.
//The app is running at http://localhost:3000/

创建组件库

  • 以上步骤都顺利的话,这时候你已经成功写出一个button组件了,那么接下来实现一个更有意思的东西:组件库,其实不难就是多个组件的集合, 跟上面创建的单一组件区别是,以前 ./src/index.js 里面放的是一个具体button组件代码,那现在要实现组件库功能, 只需要把原来./src/index.js 里面的组件代码换成export组件集合就可以了(export写法如下), 这里推荐每个组件单独写到一个文件夹中。
  • 可以参考我的层级结构, 每个组件建立一个文件夹 比如Button,Input ,然后把之前Button中的index.js跟index.css 都放到新建的Button文件中,Input 文件自己可以随便写一个, 比如下面这样:
//../src/Input/index.js
import React, {Component} from 'react';

class Input extends Component {
  render() {
    return (
      <span>  
        hello
      </span>
    )
  }
}

export default Input;



//../src/Input/index.css
暂时可以什么都不写, 就放一个空index.css
  • 我的层级结构:

//此时的 ./src/index.js 是这样的, 里面是export出的组价集合
export Button from "./Button/index.js";
export Input from './Input/index.js';

切记 切记 切记 记得引用路径一定要写对, 因为打包只打包src内部文件,引用的路径不能超出src文件范围,也不能包含src,举例来说明下:

//错误写法,以下写法本地测试没有问题,但是打包完成之后就会将src路径一起打包进去,
//会导致用户下载的npm包,使用时候会因为找不到src文件路径报错,
~~export Input from '../src/Input/index.js'; ~~  

//正确写法,不包src路径
export Button from "./Button/index.js";
  • 这时候你的Demo父组件就可以直接用组件库里面两个组件了,
    //import Button from '../../src/index';改成下面是
    import {Button ,Input} from '../../src/index.js';
  • 运行自己写的组件库
    npm start
    
    // Compiled successfully in 2013 ms.
    // The app is running at http://localhost:3000/
  • 出现以上运行结果恭喜你,你已经成功完成一个了组件库,接下来就是考虑如何发布到npm, 让大家都可以使用你的组件库

NPM账号登陆

npm账号注册

  • 注册网址: www.npmjs.com/ , 然后记下你的Username/ Password / Email 之后终端登陆npm账号要用到

npm账号登录

npm login 
Username: ma_memg       //输入用户名
Password:               //输入密码
Email: (this IS public) //输入注册邮箱
  • 不放心可以用一下命令查一下当前npm账户是谁
npm who am i
  • 查看结果:

发布到npm

  • 发布流程是先npm run build 然后 npm publish,以下详细步骤:

组件构建 npm run build

  • -- --copy-files :可将css打包进npm包( 默认是不打包css文件的 )修改 package.json 中的build, 修改 package. json 中“build”部分, 在后面添加一个-- --copy-files
//package.json

"scripts": {
->    "build": "nwb build-react-component --copy-files",
},

注意 注意 注意 发布之前确认跟上次版本号不一样,且比上一次版本号要更高, 不然会因为版本号重复或者变低导致报错,版本号在package.json中修改如下图:

//package.json
{
->  "name": "yunshang",   //输入自己组件名称 
->  "version": "1.0.1",   //每次推到npm前确保跟上次版本号不同
->  "description": "button",  //简单描述项目
    ...
}
  • 接下来运行npm run build 开始编译的组件
    npm run build
  • build之后会多出四个文件
lib:你开发的依赖模块
es: 块构建保留使用importexport语句在代码中,但将所有其他内容转为ES5
umd:在script标签中引用时使用(配置过会有,没有配置生成umd)
demo/dist: 演示使用,此部分不会推到npm

组件推送 npm publish

npm publish
  • 发布成功: (npm publish包括了npm run build)

  • 上传完成之后, www.npmjs.com 查看有没有发布成功, 搜索nwb-demo可以查到自己发布的就OK了

删除npm包

npm unpublish yunshang --force   //yunshang换成自己组件名称 

使用npm包

  • 在react项目中安装

安装

npm i yunshang  //yunshang换成自己组件名称 

//npm失败或者非常慢, 可以尝试使用cnpm安装
cnpm i yunshang  //yunshang换成自己组件名称 

示例

  • 引入样式
//引入单个组件
import { Button } from 'yunshang';  //yunshang换成自己组件名称 

//引入多个组件
import { Button, Input } from 'yunshang';  //yunshang换成自己组件名称 

使用

类型
disabledbool默认: false, true为按钮禁用状态
onClickfunction点击事件
childrenstring按钮内容

🌰举个例子

在项目中使用这个Button组件

<Button 
    onClick = {()=>{this.handleClick()}}   //onClick
    disabled = {false}   //disabled
>
    登陆  // children
</Button>