从零开始创建自己的npm组件/包(使用react)并发布到npm

一般想要发布到npm的包都是想给自己的其他项目或者是更多的人使用.所以我觉得应该更简单,更少的依赖.比如我做的

dragable-time-selector就是一个时间选择的控件,所以不需要太多的依赖.

当然为了节省时间或者是我们并不太清楚要依赖的包的原理的时候可以选择依赖他们.

虽然我们从create-react-app创建的项目也可以发布成为npm的包,但是由于我们并不需要里面很多的依赖,所以我们还是决定从零开始

做这个的原因是因为antd的timepicker我在使用的时候让我安装了moment的依赖,感觉十分臃肿而且界面不够直观,找了找网上的其他项目也都不太符合要求,一般都比较糙,所以我自己做了一个.

如果你需要引用这个控件在你的react项目中,可以使用 

npm install dragable-time-selector
或
yarn add dragable-time-selector

来安装它.

效果如下.

从零开始创建自己的npm组件/包(使用react)并发布到npm_第1张图片

 


环境搭建

首先,在工作目录下创建一个项目的文件夹,比如我们叫 my-component

执行的命令就分别是:

mkdir my-component
cd my-component

创建完以后文件夹当然是空的,我们进入到这个文件夹后直接运行npm的安装包命令即可

npm install --save -D react webpack 

执行完毕后,文件夹里面可以看到两个文件和一个文件夹

从零开始创建自己的npm组件/包(使用react)并发布到npm_第2张图片

package.json就是项目的配置文件

node_modules是该项目所依赖的包

package-lock.json是用来记录你当前安装的依赖包的来源和版本的文件.


为了更好的适应其他人的项目,以及进行我们的项目编写,我们还需要安装如下包

yarn add @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader style-loader webpack webpack-cli -D

或者

npm install -D @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader style-loader webpack webpack-cli

如果需要前端调用的时候不调用/build下的index.js而是直接能调用你的jsx文件,还可以安装

babel-plugin-transform-object-rest-spread

babel-plugin-transform-react-jsx

这两个组件

这些个包的具体作用可以网上查一下.

使用npm和yarn应该执行后的结果都是一样的,我更喜欢用yarn来管理包,感觉更快,交互也比较美观.

-D参数是把这些包都安装到开发环境,而不是生产环境,也就是说当别人npm install my-component

或者是 yarn add my-component的时候,他们并不会安装上面罗列出来的这些包,而是直接把你的包安装过去.就好像别人调用了你的dll,但是不必要把所有这个dll调用的一些类似windows api的dll也都安装一样.


稍作修改

这时我们这时候整个package.json的devDependencies字段应该像这样

"devDependencies": {
    "@babel/core": "^7.17.8",
    "@babel/preset-env": "^7.16.11",
    "@babel/preset-react": "^7.16.7",
    "babel-loader": "^8.2.3",
    "css-loader": "^6.7.1",
    "react-dom": "^17.0.2",
    "style-loader": "^3.3.1",
    "webpack": "^5.70.0",
    "webpack-cli": "^4.9.2"
  },

当然有可能你安装的时候版本跟这个不完全一样 .

接下来,我们要修改package.json文件,添加

peerDependencies

节点.这个节点的作用是 "让使用我们这个my-component包的人必须拥有跟我一样的peerDependencies里面罗列出来的包的对应版本"

这时文件完整如下:

{
  "name": "my-component",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "peerDependencies": {
    "react": "^17.0.2"
  },
  "devDependencies": {
    "@babel/core": "^7.17.8",
    "@babel/preset-env": "^7.16.11",
    "@babel/preset-react": "^7.16.7",
    "babel-loader": "^8.2.3",
    "css-loader": "^6.7.1",
    "react-dom": "^17.0.2",
    "style-loader": "^3.3.1",
    "webpack": "^5.70.0",
    "webpack-cli": "^4.9.2"
  },
  "dependencies": {}
}

注意这个peerDependencies里面的包的版本,最好跟

dependencies

里面的一样(如果包含了的话),如果非想不一样,兼容的版本也可以.


手动配置

接下来为了配置webpack,我们需要创建两个文件

webpack.config.js和.babelrc文件

注意.babelrc文件没有文件名,只有后缀

这时候的文件结构应该是这样的

从零开始创建自己的npm组件/包(使用react)并发布到npm_第3张图片

webpack.config.json我写成了下面这样(如有必要你可以自己修改一下) 

const path = require('path');

module.exports = {
  //编译的输入位置,是在项目目录下的src目录下的index.jsx,如果你使用纯js编写,那这个文件名当然就是index.js
  entry: './src/index.jsx',
  //编译的输出设置
  output: {
    //编译后的入口文件(别人用你的包的时候,引用的文件的名字,一般都是index.js
    //这样引用你的包的时候,直接就是 import MyComponent from 'my-component/build'就自动会定位到index.js.
    filename: 'index.js',
    //编译后的文件将被输出到哪个文件夹下 这里是当前项目目录下的build里面
    path: path.resolve(__dirname, 'build'),
    //意思是把我们的输出作为react组件
    libraryTarget: 'commonjs2'
  },
  module: {
    //简单理解为:在编译过程中遇到什么文件用什么工具/模块 来处理/编译 按照这样写即可.如果是ts编写,你还需要安装更多的组件.
    rules: [
      {
        //编译时找js或者jsx的文件
        test: /\.js|jsx$/,
        //不包含您这些文件夹/在遇到这些文件夹的时候,跳过.我们这里写了build是因为你编译过后的文件会在build文件夹里面,而编译过的文件你不能也不需要再编译了.
        exclude: /(node_modules|build)/,
        //当符合这样的文件格式和文件夹条件的时候,使用下面的编译组件和设置
        use: {
          //使用babel-loader
          loader: 'babel-loader',
          //使用babel-loader时候的设置
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      },
      {
        //遇到css文件的时候
        test: /\.css$/,
        //使用style-loader和css-loader处理
        use: ['style-loader', 'css-loader']
      },
    ]
  },
  //要排除哪些模块不打包呢?这个参数我不是很清楚,但是学来的时候就这样的,具体因为时间的原因我也没有测试.
  externals: {
    'react': 'commonjs react'
  }
};

.babelrc文件是这样的

{
  "presets": [",@babel/preset-env", ",@babel/preset-react"]
}

如果你使用上面的不奏效或者是要将React 组件 ES6/JSX 代码转换为 ES5

使用下面的设置,当然前提是你要安装了

"transform-object-rest-spread",
"transform-react-jsx"

这两个包

{
    "presets": ["env"],
    "plugins": [
        "transform-object-rest-spread",
        "transform-react-jsx"
    ]
}

为了让npm上传包的时候不包含我们不想上传的文件,我们可以创建一个

.npmignore的文件,也是没有文件名只有后缀,内容:

src
build
.babelrc
webpack.config.js

这个文件里面不用加入node_modules,npm上传包的时候会自动忽略掉


正式制作组件

这时候就可以正式制作我们的组件了.比如我把一个组件或者一系列组件放到src/component文件夹下

然后把入口文件放在和src同级目录下(src之前我们在webpack.config.json里面配置了.要保持一致)

根据上面的配置,我们的项目文件结构和MyComponent.jsx文件应该大概写成类似这样的:

 从零开始创建自己的npm组件/包(使用react)并发布到npm_第4张图片

index.jsx文件内容比较简单,之所以还用一个index.jsx连接到MyComponent,是因为你可能有多个类或者控件需要导出

import MyComponent from './component/MyComponent.jsx';

export default MyComponent


打包

这时候我们修改一下package.json,添加一些运行脚本,把scripts节点我改成了这样

"scripts": {
	"start": "webpack --watch",
	"build": "webpack",
	"test": "echo \"Error: no test specified\" && exit 1"
  },

其实我们只需要一个build就可以了

然后在控制台或者是终端,cmd之类的 到项目文件夹下运行  npm build 或者 yarn build

看到类似下面的页面,就算是完成了

从零开始创建自己的npm组件/包(使用react)并发布到npm_第5张图片

现在,在项目的build文件夹下,你会看到有一个index.js文件.这个文件就相当于你发布了的dll,可以提供给别人调用了.


本地怎么调用呢?

首先在这个项目的目录下执行 

yarn link

这一步,就是把当前的项目(要发布的包)创建连接

命令,这会把你当前的这个小项目当做一个注册给了电脑系统上的全局可访问的dll,使用的时候,电脑自己会找到他.

在别的项目中想使用这个包的话 只需要连接到那个组件就可以了.

命令是:

yarn link my-component

然后,你可以在使用这个组件的时候,比如在你目标程序的某个页面下使用

import MyComponent from 'my-component'

就可以在标签中插入他了.像使用其他组件一样.


发布到NPM平台

首先要到npmjs.com注册你的账号.这个就不用说了.

然后在项目目录下使用控制台/终端/cmd 运行

npm login

然后输入注册的npm的用户名 密码 邮箱 和邮箱内收到的验证码就登陆了.

如果登陆不成功的话,请检查NPM的源是否准确

NPM源可以使用nrm包来进行管理.我其他文章有写到

使用

npm publish

可以把这个包发布到npm,但是注意发布包的时候如果提示权限不足,要先在npmjs上搜索一下有没有叫这个名字的包.如果没有你才可以发布.如果有,你要改名字才能发布.改名字的方法就是修改项目下的package.json文件下的

name

字段


更新和版本控制

我主要是要介绍如何制作并成功的发布,至于版本控制有许多命令,我们先弄简单些的

npm version patch
npm version minor
npm version major

三条命令很常用,基本就是从上到下分别对应了

0.0.0到1.1.1的

patch 最后一位,小修改用他

minor 中间一位,一般功能升级用他

major 最前面一位,大改动或者跟之前的版本不兼容了用他

也就是说从0.0.0到0.0.1只需要执行一次 npm version patch就可以自动升版本号了

然后执行 npm publish 就把新版本发布到云端了

从0.0.1到0.1.0 使用 npm version minor

从0.1.0到1.0.0使用 npm version major

注意,左边版本不会把右边子版本号在升级的时候携带.也就是

npm version minor 不会把 0.0.1升级为0.1.1而是 0.1.0


一点建议

非常有用的"最小系统法"在很多场景都适用.比如像现在你想开发的组件,尽可能的只添加有必要的东西.否则繁杂的东西可能都是祸根,

知其然不如知其所以然,某些时候如果真的时间有限你可以照抄一些东西,如果运气好,一次就抄成功.但如果你都把道理弄清楚了(学会了),以后在别的地方,别的项目上等等能省下的时间可能不止现在能节省的这么多.

如果你有对我的文章,或者在这个项目上的issue,请告诉我

这个项目的源代码可以在这里获取:GitHub - Norman-w/time-selector

你可能感兴趣的:(React,npm,react,js)