leiwuhen-67's blog leiwuhen-67's blog
首页
    • 《Vue》笔记
    • 《React》笔记
    • 《NodeJs》笔记
    • 《CSS》笔记
    • 《Redis》笔记
    • 基础入门
    • 《Mock》笔记
    • 《MySQL》笔记
    • 《Git》相关
影音视听
收藏
关于
GitHub (opens new window)

我的公众号

首页
    • 《Vue》笔记
    • 《React》笔记
    • 《NodeJs》笔记
    • 《CSS》笔记
    • 《Redis》笔记
    • 基础入门
    • 《Mock》笔记
    • 《MySQL》笔记
    • 《Git》相关
影音视听
收藏
关于
GitHub (opens new window)
  • React

    • 使用React脚手架快速搭建项目
    • hooks之useEffect
    • React之事件绑定及简写方式
    • React之props传值并对其进行限制
    • React之Refs的基本使用
    • React之生命周期钩子
    • React之key的使用
    • React之代理服务器配置
    • React之封装全局Loading组件
    • React之消息的发布-订阅(pubsub-js)
    • React之Redux的基本使用
    • React之react-redux的基本使用
    • React之redux的数据持久化存储
    • React之路由懒加载
    • React之Render Props的使用
    • React之createBrowserRouter
    • React之路径别名@配置
    • React之craco打包优化配置
    • React之项目国际化
    • React之postcss-pxtorem移动端适配
    • React之使用vite创建项目
    • React之ts类型标注汇总
    • React之使用 ant design搭建后台管理之踩坑
    • React之路由切换动画
    • React之使用vite创建组件库并发布到npm
      • 项目创建及基础配置
      • package.json文件配置说明
      • 发布到npm以及可能会遇到的问题
      • 补充
        • 1、静态资源配置
        • 2、组件中使用module css配置
    • React之项目打包部署到nginx
    • React之自定义组件添加className与style
  • React Native

  • 《React》笔记
  • React
心欲无痕
2024-08-14
目录

React之使用vite创建组件库并发布到npm

在工作过程中,经常是好几个项目都需要用到同一个或几个功能,为了偷懒,所以想着研究下能不能将这几个功能封装成组件库,然后放到 npm 上,每次需要使用时,就安装一下就可以使用了。
说干就干,这里的搭建环境是 vite+react+ts

# 项目创建及基础配置

1、初始化项目,如创建 my-react-library 文件夹,并进入,然后执行 npm init 初始化项目

2、安装 Vite、React、TypeScript 以及相关依赖

npm install react react-dom
npm install --save-dev typescript vite @vitejs/plugin-react vite-plugin-dts
1
2

3、设置 TypeScript
在项目根目录下创建一个 tsconfig.json 文件,配置如下:

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "jsx": "react-jsx",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "emitDeclarationOnly": true,
    "outDir": "dist",
    "moduleResolution": "node"
  },
  "include": ["packages"],
  "exclude": ["node_modules", "dist"]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

ps:
1、include:表示你需要将项目中的 packages 目录下的内容进行打包
2、outDir:表示打包后的文件夹的名称

4、在项目根目录下创建 packages 文件夹,用来存放各种组件
以 Button 组件为例,在 packages 文件夹下创建 Button 文件夹,在 Button 文件夹下创建 Button.tsx、index.ts、index.css 文件

// /packages/Button/Button.tsx
import React from "react";
import "./index.css"

export interface ButtonProps {
    text: string;
    onClick: () => void;
}

const MyButton: React.FC<ButtonProps> = ({ text, onClick } = {
    text: 'Button',
    onClick: () => {
        console.log('click');
    }
}) => {
    return (
        <div>
            <button className="my-button" onClick={onClick}>{ text }</button>
        </div>
    );
};

export default MyButton;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

/packages/Button/index.css

.my-button {
  width: 100px;
  height: 20px;
  background-color: #000;
  color: #fff;
  border-radius: 5px;
  cursor: pointer;
}
1
2
3
4
5
6
7
8
// /packages/Button/index.ts
import Button from './Button';
export type { ButtonProps } from './Button';
export default Button;
import './index.css';
1
2
3
4
5

5、添加打包配置
在项目根目录下创建 vite.config.ts 文件,配置如下:

import { defineConfig } from 'vite'
import { resolve } from 'path'
import react from '@vitejs/plugin-react'
import dts from 'vite-plugin-dts';  // 用于输出 .d.ts类型文件

export default defineConfig({
  plugins: [
    react(),
    dts({
      insertTypesEntry: true,
    }),
  ],
  build: {
    lib: {
    	// 组件库源码的入口文件
      entry: resolve(__dirname, 'packages/index.ts'),
      name: 'my-react-component',
      // 文件名称
      fileName: (format) => `my-lib.${format}.js`,
    },
    rollupOptions: {
    	// 处理那些你不想打包进库的依赖
      external: ['react', 'react-dom'],
      output: {
      	// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
        globals: {
          react: 'React',
          'react-dom': 'ReactDOM',
        },
      },
    },
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

6、创建组件库的入口文件
在 packages 目录下创建 index.ts 文件,将所有组件及 ts 类型导出

export { default as Button } from './Button';
export type { ButtonProps } from './Button';
1
2

7、更新 package.json 文件,添加如下配置

"type": "module",
"files": [
  "dist"
],
"main": "./dist/my-lib.umd.js",
"module": "./dist/my-lib.es.js",
"types": "./dist/index.d.ts",
"scripts": {
  "dev": "vite",
  "build": "tsc -b && vite build"
},
"peerDependencies": {
  "react": ">=16.8",
  "react-dom": ">=16.8"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# package.json 文件配置说明

1、files:包含在发布包中的文件,这里指定了 dist 目录,确保打包输出的文件会被包含在发布包中。。
2、main: 指定 CommonJS 入口文件(通常用于 Node.js 环境)
3、module:指定 ES Module 入口文件(通常用于现代前端工具链,如 Webpack、Rollup 等)
4、types:指定类型声明文件入口
5、peerDependencies:提示宿主环境去安装满足插件 peerDependencies 所指定依赖的包,然后在插件 import 或者 require 所依赖的包的时候,永远都是引用宿主环境统一安装的 npm 包,最终解决插件与所依赖包不一致的问题

按如上步骤执行完后,执行打包命令,npm run build,生成文件结构如下:

# 发布到 npm 以及可能会遇到的问题

然后执行 npm login 登录 npm,当然,前提是你得先有一个 npm 账户,如果没有就创建一下吧,登录完后,执行 npm publish 或 npm publish --access public。
这里可能会遇到这几个问题:
1、由于创建的项目是私有的,会报错,即 package.json 中有 "private": true 的设置,将其更改为 false 即可
2、使用非官方镜像源执行提交命令,如 cnpm 或者淘宝镜像源等等,可能会报错误,将镜像源切换为官方的 (https://registry.npmjs.org/) 即可(推荐安装 nrm 解决)
3、由于 npm 服务器在国外,所以可能会很慢,建议耐心等待,当然,也可通过代理解决(npm config set proxy 代理 ip:port 或 npm config set https-proxy 代理 ip:port)(移除代理:npm config delete proxy 或 npm config delete https-proxy)
4、由于与 npm 上已存在的项目冲突,会发布失败,建议更改 package.json 中的 name 字段的值
5、如果是已经发布过,需要重新发布,需要更改 package.json 中 version 字段,更改版本号,否则会发布失败

发布到 npm 成功后,使用如下:
1、安装发布的组件

// 组件的名字是你package.json文件中的name
npm install react-lib-lei
1
2

2、在项目中使用如下,一个具有 ts 类型支持的组件就可以成功使用了

import { Button } from "react-lib-lei";
import "react-lib-lei/dist/style.css"

const MyComponent = () => {
	const handleClick = () => {
		console.log("hello world")
	}

	return (
		<div>
			<Button text="hello" onClick={ handleClick } />
		</div>
	)
}

export default MyComponent;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

至此,一个组件库的发布与使用就成功解决了

# 补充

# 1、静态资源配置

例如图片存放在了 /src/assets/ 目录下,那么可以借助 vite-plugin-static-copy 插件来处理静态资源的复制和引入,同时配置路径别名,后续要用,在 vite.config.ts 中增加如下配置

import {viteStaticCopy } from 'vite-plugin-static-copy';
import { resolve } from 'path';

export default defineConfig({
	resolve: {
	  alias: {
	    '@': path.resolve(__dirname, 'src'),
	  },
	},
	plugins: [
		viteStaticCopy({
		  targets: [
		    {
		      src: 'src/assets/*',
		      dest: 'assets'
		    }
		  ]
		})
	],
	build: {
		assetsDir: 'assets',
		assetsInlineLimit: 0, // 禁用资源内联
	}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

修改 package.json,files 值改为:

"files": [
  "dist",
  "assets"
]
1
2
3
4

tsconfig.json 中增加如下配置:

{
	"compilerOptions": {
		"baseUrl": ".",
		"paths": {
		  "@/*": ["src/*"]
		}
	}
}
1
2
3
4
5
6
7
8

此时,在组件中使用 import xx from "@/assets/xxxx" 就行了,这样打包以后,组件中也能正常访问到图片资源,不会丢失

package.json 部分配置如下:

{
	"name": "react-lib-lei",
	"version": "0.0.8",
	"type": "module",
	"files": [
	  "dist",
	  "assets"
	],
	"main": "./dist/my-lib.umd.js",
	"module": "./dist/my-lib.es.js",
	"types": "./dist/index.d.ts",
  // .......
}
1
2
3
4
5
6
7
8
9
10
11
12
13

vite.config.ts 配置如下:

import { defineConfig } from 'vite'
import path, { resolve } from 'path'
import react from '@vitejs/plugin-react'
import dts from 'vite-plugin-dts';
import { viteStaticCopy } from 'vite-plugin-static-copy';

export default defineConfig({
	resolve: {
	  alias: {
	    '@': path.resolve(__dirname, 'src'),
	  },
	},
	plugins: [
		react(),
		dts({
		  insertTypesEntry: true,
		}),
		viteStaticCopy({
		  targets: [
		    {
		      src: 'src/assets/*',
		      dest: 'assets'
		    }
		  ]
		})
	],
	base: './',  // 确保资源路径相对于当前目录
	build: {
	  assetsDir: 'assets',
	  assetsInlineLimit: 0, // 禁用资源内联
	  lib: {
	    entry: resolve(__dirname, 'packages/index.ts'),
	    name: 'my-react-component',
	    fileName: (format) => `my-lib.${format}.js`,
	  },
	  rollupOptions: {
	    external: ['react', 'react-dom'],
	    output: {
	      globals: {
	        react: 'React',
	        'react-dom': 'ReactDOM',
	      },
	      assetFileNames: 'assets/[name].[ext]'
	    },
	  },
	}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

tsconfig.json 配置如下:

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "jsx": "react-jsx",
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "allowImportingTsExtensions": true,
    "declaration": true,
    "outDir": "dist",
    "emitDeclarationOnly": true,
    "isolatedModules": true
  },
  "include": ["packages"],
  "exclude": ["node_modules", "dist"]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 2、组件中使用 module css 配置

由于使用了 ts,而 ts 默认并不识别 .module.css 文件。因此需要创建或修改一个类型声明文件来解决这个问题。
在项目根目录下创建 global.d.ts 文件

declare module '*.module.css' {
    const classes: { [key: string]: string };
    export default classes;
}
1
2
3
4

在 tsconfig.json 中配置修改如下:

{
	"include": ["packages", "global.d.ts"]   // 增加global.d.ts配置
}
1
2
3

现在就可以在组件中使用 module css 了

编辑 (opens new window)
上次更新: 3/4/2025, 5:46:30 PM
React之路由切换动画
React之项目打包部署到nginx

← React之路由切换动画 React之项目打包部署到nginx→

Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式