使用 Vite 和 Typescript 创建 React 组件库
大多数时候,我们会使用自己喜欢的工具来创建 React 应用:Create React App、Next、Gatsby……
但是,构建组件库时,情况就不同了。选择并不简单。本文将展示如何使用 Vite 和 Typescript 创建库。
为什么选择 Vite?
Vite 是一款性能卓越的现代前端工具。您可以点击此处了解更多详情。它开箱即用,支持 TypeScript 和库包。因此,它是创建 React 库的理想选择。
如何构建和组织我们的项目?
让我们开始创建一个 Monorepo。我们使用 Yarn 工作区来管理依赖项。
要配置 Monorepo,我们需要在仓库的根目录创建一个 package.json 文件。
{
"name": "lib-example",
"private": true,
"workspaces": {
"packages": [
"packages/*",
"sites/*"
]
},
}
该存储库有两个文件夹:
- 包含组件库包的包
- 包含测试库的站点
这是树结构。
react-library-vite-example
|- packages
| |- my-lib
|- sites
| |- my-site
|- package.json
|- yarn.lock
库包
在 packages 文件夹中,让我们创建一个新的 Vite 项目:
yarn create vite my-lib --template react-ts
默认情况下,它会创建一个配置了 TypeScript 的 React Web 应用。现在,我们需要对其进行自定义,以使用 Vite 的库模式。
首先,我们必须安装一个 vite 插件来帮助我们生成组件的类型定义。
yarn add --dev vite-plugin-dts
为了捆绑库,我们需要更新 vite.config.js 文件。
import react from '@vitejs/plugin-react';
import path from 'node:path';
import { defineConfig } from 'vite';
import dts from 'vite-plugin-dts';
export default defineConfig({
plugins: [
react(),
dts({
insertTypesEntry: true,
}),
],
build: {
lib: {
entry: path.resolve(__dirname, 'src/lib/index.ts'),
name: 'MyLib',
formats: ['es', 'umd'],
fileName: (format) => `my-lib.${format}.js`,
},
rollupOptions: {
external: ['react', 'react-dom', 'styled-components'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'styled-components': 'styled',
},
},
},
},
});
请注意,将任何不想打包到库中的依赖项外部化也很重要:react、react-dom 和 styled-components。
我们的 rollup 配置会生成两种打包格式:es 和 umd。
我们将以下按钮组件(MyButton.tsx)添加到我们的库中作为示例。
import styled from 'styled-components';
const MyButton = styled.button`
border: none;
border-radius: 0.5rem;
background-color: #186faf;
color: hsl(0deg, 0%, 98%);
padding: 0.75rem;
cursor: pointer;
&:hover {
background-color: #0a558c;
}
&:focus {
outline: none;
box-shadow: 0 0 0 2px #62b0e8;
background-color: #0a558c;
}
`;
export default MyButton;
所有公共的 React 组件都导出到文件中src/lib/index.ts
。
export { default as MyButton } from './MyButton';
以下是我们库的更新后的 package.json:
{
"name": "my-lib",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"styled-components": "^5.3.3"
},
"devDependencies": {
"@babel/core": "^7.16.12",
"@types/node": "^17.0.12",
"@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11",
"@types/styled-components": "^5.1.21",
"@vitejs/plugin-react": "^1.1.4",
"acorn-jsx": "^5.3.2",
"babel-loader": "^8.2.3",
"typescript": "^4.5.5",
"vite": "^2.7.13",
"vite-plugin-dts": "^0.9.9"
},
"license": "UNLICENSED",
"peerDependencies": {
"react": "^16.8.0 || 17.x",
"react-dom": "^16.8.0 || 17.x",
"styled-components": "^5.0.0"
},
"files": [
"dist"
],
"main": "./dist/my-lib.umd.js",
"module": "./dist/my-lib.es.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/my-lib.es.js",
"require": "./dist/my-lib.umd.js"
}
}
}
运行yarn build来编译库。
当我们将依赖项(外部依赖项除外)打包到库中时,我们必须清理已发布的 npm 包的 package.json 文件。我们通过添加 prepack 脚本来实现这一点。
"prepack": "json -f package.json -I -e \"delete this.devDependencies; delete this.dependencies\"",
我使用 CLI 来处理 JSON(yarn add -D json
)。
测试组件库的网站
让我们首先在 sites 文件夹中创建一个新的 Vite 项目。
yarn create vite my-site --template react-ts
我们需要在 package.json 文件中添加以下依赖项来测试我们的组件库:
"dependencies": {
"my-lib": "*",
...
},
现在,我们可以引用并使用我们的按钮组件。
import { MyButton } from 'my-lib';
function App() {
return (
<div className="App">
...
<MyButton onClick={...}>Click here!</MyButton>
...
</div>
);
}
export default App;
运行yarn install和yarn run dev来启动开发服务器。
配置故事书
我们还想为我们的 UI 组件创建文档。Storybook 是一个很棒的项目,可以帮助我们为 React 组件创建一个 Playground。
运行以下命令来配置 Storybook:
cd /packages/my-lib && npx sb init --builder storybook-builder-vite
在撰写本文时,交互插件与 Vite 无法良好兼容。以下是自定义配置(.storybook/main.js):
module.exports = {
stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
],
framework: "@storybook/react",
core: {
builder: "storybook-builder-vite",
},
};
最后,我们为按钮组件创建一个故事文件。
import { ComponentMeta, ComponentStoryObj } from '@storybook/react';
import MyButton from './MyButton';
const meta: ComponentMeta<typeof MyButton> = {
title: 'Design System/MyButton',
component: MyButton,
};
export default meta;
export const Primary: ComponentStoryObj<typeof MyButton> = {
args: {
disabled: false,
children: 'Hello',
},
};
运行yarn run storybook来启动故事书。
如果您想了解有关 Storybook 的更多信息,请查看官方文档。
下一步是什么?
我们刚刚创建了一个优秀的 Vite 启动项目。但是,我们还可以进一步配置其他工具,例如 eslint、prettier、jest……
你可以在 Github 上找到源代码。
这对我的项目很有帮助。希望它也能帮到你。