前言

最近阅读了下 vite 的文档,发现它有个库模式用来打包挺方便的,因而写篇博客记录下折腾过程。

基本配置

执行如下命令创建一个 React + TypeScript 的项目

pnpm create vite

删除 src 和 public 文件夹,创建 example 和 packages 文件夹,其中 example 存放组件示例或者调试组件,packages 存放组件源码。另外别忘了修改根目录 index.html script路径。

├── node_modules

├── packages

├── example

├── index.html

├── package.json

├── pnpm-lock.yaml

├── tsconfig.json

├── tsconfig.node.json

└── vite.config.ts

// index.html

注:相关 eslint prettier tsconfig 的配置请自行查看末尾 git 仓库,这不是本文的重点。

下面我们打开 vite.config.ts,对打包进行配置(记得先安装下 @types/node )

import { readFileSync } from 'fs'

import path from 'path'

import { defineConfig } from 'vite'

import react from '@vitejs/plugin-react'

const packageJson = JSON.parse(

readFileSync('./package.json', { encoding: 'utf-8' }),

)

const globals = {

...(packageJson?.dependencies || {}),

}

function resolve(str: string) {

return path.resolve(__dirname, str)

}

export default defineConfig({

plugins: [react()],

build: {

// 输出文件夹

outDir: 'dist',

lib: {

// 组件库源码的入口文件

entry: resolve('packages/index.tsx'),

// 组件库名称

name: 'demo-design',

// 文件名称, 打包结果举例: suemor.cjs

fileName: 'suemor',

// 打包格式

formats: ['es', 'cjs'],

},

rollupOptions: {

//排除不相关的依赖

external: ['react', 'react-dom', ...Object.keys(globals)],

},

},

})

此时你在 packages/index.tsx 文件夹中任意 export 些代码,他应该可以被正确打包成 CommonJS 与 ESM 了。

组件编写

为了简单起见,我们组件就编写一个有类型支持且可以切换颜色的 Tag。

安装依赖

pnpm i less clsx -D

下面这些 react 代码就不介绍了

编写 packages/Tag/interface.ts

import { CSSProperties, HTMLAttributes } from 'react'

/**

* @title Tag

*/

export interface TagProps

extends Omit, 'className' | 'ref'> {

style?: CSSProperties

className?: string | string[]

/**

* @zh 设置标签背景颜色

* @en The background color of Tag

*/

color?: Colors

}

type Colors = 'red' | 'orange' | 'green' | 'blue'

编写packages/Tag/index.tsx

import clsx from 'clsx'

import { forwardRef } from 'react'

import './style'

import { TagProps } from './interface'

const Tag: React.ForwardRefRenderFunction = (

props,

ref,

) => {

const { className, style, children, color, ...rest } = props

return (

ref={ref}

style={style}

{...rest}

className={clsx(className,'s-tag', `s-tag-${color}`)}

>

{children}