Developing Your Component Library with Vite and TailwindCSS
Introduction Demonstration Video https://www.bilibili.com/video/BV1EST3zPEyP/?spm_id_from=333.1387.homepage.video_card.click
References https://juejin.cn/post/7112295067682865166
https://juejin.cn/post/7046187185615142949
Code Repository https://gitee.com/malguy/vite-components-lib-tutorial
Initializing the Project Creating a Vite Project Use the command line directly:
1 2 3 pnpm create vite react-components cd react-components pnpm i
You can also use my CLI panel (shameless plug 😁🤓)
malred/cli-panel
No internet connection needed, as it uses file copying to create the project.
Installing Tailwind Use Tailwind v3
Installation - Tailwind CSS
1 2 3 pnpm install -D tailwindcss@3 postcss autoprefixer # npx tailwindcss init -p pnpm dlx tailwindcss@3 init -p
Add the paths to all template files in the **<font style="color:rgb(15, 23, 42);">tailwind.config.js</font>**
file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export default { content : [ "./index.html" , "./src/**/*.{js,ts,jsx,tsx}" , "./src/**/*.{vue,js,ts,jsx,tsx}" , "./src/**/*.{svelte,js,ts,jsx,tsx}" , ], theme : { extend : {}, }, plugins : [], }
Add the **<font style="color:rgb(15, 23, 42);">@tailwind</font>**
directives for each layer of Tailwind to your **<font style="color:rgb(15, 23, 42);">./src/app.css</font>**
file.
1 2 3 @tailwind base;@tailwind components;@tailwind utilities;
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 import './button.css' import * as React from "react" ;interface Props { size : 'lg' | 'md' | 'sm' children : string | React .ReactNode } const Button = ({ size, children }: Props ) => { const className = size + " base " return ( <button className ={className} > {children} </button > ); }; export default Button ;
If you find the Tailwind styles too long, you can write a CSS file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 button { &.base { @apply text-white bg-blue-500 rounded-md } &.sm { @apply text-xs p-2 } &.md { @apply text-sm p-4 } &.lg { @apply text-lg p-8 } }
Exporting in index.js 1 2 3 4 5 6 7 8 9 // !!! 重要 包含@tailwind的css必须导出, 否则新项目会丢失变量 !!! import './index.css' import './App.css' import Button from "./components/button/index.jsx"; export { Button as MalButton }
Modifying the Vite Configuration File 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 import {defineConfig} from 'vite' import react from '@vitejs/plugin-react' import path from 'path' // const path = require("path"); const resolvePath = (str) => path.resolve(__dirname, str); // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], // 防止 vite 将 rgba() 颜色转化为 #RGBA 十六进制 cssTarget: 'chrome61', resolve: { alias: { "@": path.resolve(__dirname, "./src"), }, }, // 打包编译配置 build: { rollupOptions: { // 请确保外部化那些你的库中不需要的依赖 external: ["react", "react-dom"], output: { // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量 globals: { react: "react", "react-dom": "react-dom", }, }, }, lib: { // 打包入口文件, 使用时从入口进行寻找依赖 entry: resolvePath("src/index.js"), name: "mal-react-components", // 打包后文件名 format表示不同的规范(commonjs之类的) // 如果打包成 UMD 格式,文件名可能是 mal-vue3-components.umd.js。 // 如果打包成 ES Module 格式,文件名可能是 mal-vue3-components.es.js fileName: format => `mal-react-components.${format}.js`, }, } })
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 import {defineConfig} from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig ({ plugins : [vue ()], build : { rollupOptions : { external : ['vue' ], output : { globals : { vue : 'Vue' , }, }, }, lib : { entry : './src/index.js' , name : 'mal-vue-components' , fileName : (format ) => `mal-vue3-components.${format} .js` , }, } })
If using TypeScript
1 2 3 pnpm i @rollup/plugin-typescript tslib # 在vite.config文件里使用node的依赖需要安装 pnpm i @types/node --save-dev
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 48 49 50 import {defineConfig} from 'vite' import react from '@vitejs/plugin-react' import typescript from '@rollup/plugin-typescript' import {resolve} from "node:path" ;const resolvePath = (str : string ) => resolve (__dirname, str);export default defineConfig ({ plugins : [react ()], resolve : { alias : { "@" : resolve (__dirname, "./src" ), }, }, build : { rollupOptions : { external : ["react" , "react-dom" ], output : { globals : { react : "react" , "react-dom" : "react-dom" , }, }, plugins : [ typescript ({ target : "es2015" , rootDir : resolvePath ("src/" ), declaration : true , declarationDir : resolvePath ("dist" ), exclude : resolvePath ("node_modules/**" ), allowSyntheticDefaultImports : true , }), ], }, lib : { entry : resolvePath ("src/index.ts" ), name : "mal-react-components" , fileName : format => `mal-react-components.${format} .js` , }, }, })
Packaging and Publishing
Usage To test locally, you can use
1 2 3 4 # 在库的目录执行 npm link # 在要使用的目录中执行 npm link [自己写的库的名称]
However, I previously tried this and it always failed. My solution was to directly copy the packaged files into the project and then import the dependencies from there.