发布前端组件的步骤

7 min read,created at 2024-07-03
前端组件componentreactcamel-ui

1 背景

我之前封装了十几个react组件,后面想在其他的个人项目中进行使用,所以需要把开发好的组件库发布到npm上。

本文讲一下都需要哪些步骤,组件以vite + react进行开发的,如果是其他打包工具流程也是类似的。

2 流程

首先假设你已经开发好了组件,并且也是使用的vite + react

2.1 package.json

修改package.json如下,其中有几个入口文件还有.d.ts还没有准备好,我们后面会介绍如何创建。

package.json
{
  "name": "@sunwu51/camel-ui",   // 先到npm上搜一下,有没有同名的,保险的方案就是@username/xxx
  "version": "0.0.1",
  "type": "module",
  "main": "dist/camel.umd.js",   // umd模式下的 import require用这个文件
  "module": "dist/camel.es.js",  // es模式下 import require用这个,这个比较重要,前端开发都只用es
  "types": "dist/types/index.d.ts",  // 类型声明的d.ts文件,方便别人引入提供智能提示
  "keywords": [                  // npm的关键字,可有可无
    "react",
    "component",
    "react-aria",
    "camel-ui"
  ],
  "author": "Frank",           // 作者 证书 git仓库, 可有可无
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/sunwu51/camel-ui.git"
  },
  "publishConfig": {          // 声明是public的,带@username的默认是private
    "access": "public"
  },
  "files": [                  // 需要上传到npm的文件,只上传dist即可src等不需要
    "dist"
  ],
  "scripts": {
    //...
  },
  "dependencies": {
    //...
  },
  "peerDependencies": {     // 把react react-dom从dependencies移到peerDependenies,
    "react": "^18.2.0",     // 项目中会自己引入,不要在组件库引入
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    // ...
  }
}

2.2 types.tsindex.d.ts

一般而言开发组件库,最好使用ts并配有类型声明文件,这样在用户使用的时候,才能有每个组件的属性智能提示。当然我们还要把这些类型声明出去才能被使用。

首先创建type.ts,把组件的各种props属性进行声明如下:

type.ts

......

export interface ButtonProps extends BaseProps, AriaButtonOptions<'button'> {}
export interface BadgeProps extends BaseProps {}
export interface CardProps extends BaseProps {}
export interface CheckboxProps extends BaseProps, ToggleStateOptions, AriaCheckboxProps {}

在我们组件开发过程中,就需要用到这些属性,例如BadgeProps组件中是这样的,通过types.ts引入属性。

BadgeProps.tsx
import './Badge.css'
import {cn} from '../cn'
import { BadgeProps } from '../../types'

function Badge(props: BadgeProps) {
    return <>
        <span className={ cn("badge-container", props.className) } style={{...props.style}}>
            {props.children}
        </span>
    </>
}

而对于使用方来说,则是通过index.d.ts,也对应了pacakge.json中的types属性配置。

index.d.ts
export * from './types';

declare module 'camel-ui' {
  export * from './types';
}

2.3 vite.config.tstsconfig.json

需要先安装两个插件:

  • vite-plugin-dts插件用来生成.d.ts类型声明的文件,这对于react组件库很重要,他会对每个组件都生成一个类型声明的文件,智能提示很有用,并且还会拷贝上面的index.d.ts文件。
  • vite-plugin-lib-inject-css用来内连cssjs中,使得只引入js组件,就自带了样式,不需要再引一次css。当然如果你本来就用了css-in-js的方案,那这个组件可能是不需要的。
$ npm i -D vite-plugin-lib-inject-css vite-plugin-dts

接下来是最重要的修改vite.config.ts,默认的build行为是以index.html为入口,打包各种js文件,使其成为一个web项目。但是组件库不同,我们要配置buildlib

vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'// 这里我用的swc如果vite项目没选swc的话,应该是另一个插件
import { libInjectCss } from 'vite-plugin-lib-inject-css'
import dts from 'vite-plugin-dts';
import path from 'path';

export default defineConfig({
  plugins: [react(), 
    libInjectCss(), // 内连css
    dts({           // 生成所有组件的dts声明到dist/types目录
      tsconfigPath: './tsconfig.json', // 指定tsconfig文件
      outDir: 'dist/types',
    }),],

  build: {
    lib: {
      entry: path.resolve(__dirname, 'src/index.ts'),
      name: 'CamelUI',
      fileName: (format) => `camel.${format}.js` // 默认输出format有俩,umd和es
    },
    rollupOptions: {
      external: ['react', 'react-dom'], // 排除react的打包,减小包体积
      output: {
        globals: {
          react: 'React',
          'react-dom': 'ReactDOM'
        }
      }
    }
  }
});

然后是tsconfig.json添加两行。

tsconfig.json
{
    ...
+    "declaration": true,
+    "declarationDir": "./dist/types",
    ...
}

2.4 打包与本地测试

$ npm run build

得到dist目录结构如下,camel.{format}.js是前面配置的主要入口js文件,index.css是所有的样式,typesdts插件生成的各种组件和属性声明。

└── 📁dist
    └── camel.es.js
    └── camel.umd.js
    └── index.css
    └── 📁types
        └── App.d.ts
        └── 📁components
            └── 📁Badge
                └── Badge.d.ts
            ...
            └── BaseProps.d.ts
        └── index.d.ts
        └── main.d.ts
        └── types.d.ts

在上传到npm之前最好先本地测试一下

# 在当前组件库目录下运行
$ npm link

# 然后到一个测试项目中运行
$ npm link @sunwu51/camel-ui # 这里换成你的组件库名

此时就会直接把组件库的目录,链接到测试项目的node_modules中,就可以测试使用了。

2.5 发布npm

如果没有npm账号,先去注册一个,然后在组件库项目下登录。

$ npm login #根据提示完成登录

$ npm publish 

发布完成后,即可在npm页面中看到,并且因为是public的,所以其他人也可以浏览和安装。

image