最小可shadcn可初始化环境
一般我们会将shadcn集成到现有的前端框架项目中,比如vite、nextjs等等。
但是如果我们要把shadcn抽离出来,成为一个单独的组件库项目,供多个项目使用,那么我们就要创建一个最小可运行的环境,来支持shadcn初始化以及后续的组件安装。
我们在执行pnpm dlx shadcn init的时候,会进行一些检查,如果不符合要求,是不能进行初始化的,通过执行pnpm dlx shadcn init,如果出现下面的提示,则说明我们当前的环境是符合shadcn初始化要求的。
✔ Preflight checks.
✔ Verifying framework. Found Vite.
✔ Validating Tailwind CSS config. Found v4.
✔ Validating import alias.
Preflight checks
预检检查,会检查项目中是否已经被初始化过。
这个不重要!
Verifying framework
验证框架,会检查项目中是否使用了vite、nextjs等框架。
所以我们只需要在项目中新建一个空的vite.config.js文件即可,这样shadcn就会识别为vite项目了。
Validating Tailwind CSS config
验证tailwindcss配置,会检查项目中是否已经安装了tailwindcss,并且在项目中存在任意一css文件且有@import "tailwindcss";,比如我们可以
|--src|--base-styles.css
Validating import alias
验证导入别名,会检查项目中是否已经配置了导入别名。
需要我们创建一个最小的tsconfig.json文件,内容如下:
{"compilerOptions": {"paths": {// @repo/shadcn-cmpnts为项目的包名,即package.json的name属性,如果非多仓,则@直接对应root即可"@repo/shadcn-cmpnts/*": ["./src/*"]}}
}
这会决定一会初始化shadcn时候期生成配置文件components.json中aliases的值。
而配置文件components.json中aliases的值又会决定组件下载路径。
验证
现在你已经配置好所有的shadcn可具备初始化的环境了。我们立刻pnpm dlx shadcn init进行shadcn初始化吧,
它会在你配置的tsconfig.json的paths中新建一个@repo/xxx/*的别名对应的目录下:
- 新建一个
components目录,用于存放组件。 - 新建一个
lib目录,用于存放工具函数,比如utils.ts。
最后你可以pnpm dlx shadcn add button来安装一个组件了。
对了,我们现在可以将 vite.config.js删除了,毕竟他只是为了让shadcn初始化的时候识别框架类型而已!
优化(可选)
实际上,在安装完毕后你还可以将 tailwindcss 卸载,然后创建一个 tailwind-config的单仓,将刚生成的components.json里的 css配置 改为向tailwind-config单仓索取
shadcn-cmpnts>components.json
{{//..."tailwind": {// ..."css": "@repo/tailwind-config",},}
}
这样以来,我们的的shadcn组件仓@repo/shadcn-cmpnts将变的更为干净,不再包含tailwind相关内容,请看下面谈 如何抽离tailwind!
抽离tailwind
因为多个仓库可能都会用到tailwind,所以我们可以将tailwind抽离出来,成为一个单独的仓库,供多个仓库使用。
我们初始化一个仓库,包名改为@repo/tailwind-config,然后安装 tailwind依赖!
将@repo/shadcn-cmpnts中的初始化后的xxx.css(即包含@import "tailwindcss";的那个css文件)拷贝到@repo/tailwind-config中,并加上如下代码
/* 只要你在任意一个会被 Tailwind 扫描到的 CSS 文件里写了 @source,它就把这些路径追加到扫描列表,效果与在被v4抛弃的 tailwind.config.ts 里写 content 完全等价。 */
@source "../**/*.{ts,tsx}";
@source "../../../../apps/**/*.{ts,tsx}";
@source "../../../../packages/**/*.{ts,tsx}";
最后导出!
{"name": "@repo/tailwind-config","version": "0.0.0","type": "module","private": true,"exports": {".": "./base-styles.css","./postcss": "./postcss.config.js" //可选},"devDependencies": {"postcss": "^8.5.6", //可选"tailwindcss": "^4.1.16"}
}
这样我们在其它仓库包中,就可以直接使用了:
比如@repo/web中,可以直接导入到此项目的style.css中,而不要在安装tailwindcss包了(但是如果@tailwindcss/vite还是要用的)
@import "@repo/tailwind-config";
在tailwind中,也可以直接给shadcn指定改依赖的css,而不要在安装tailwindcss包了
"tailwind": {// ..."css": "@repo/tailwind-config",
},
其它补充
@import "tailwindcss"
🚨 魔法语句,不是文件路径,
这并非导入tailwindcss这个style文件(实际上也没有这个文件)
@import "tailwindcss"; 只是 “按下开关”——
它让 Vite 去调 @tailwindcss/vite 里预先注册好的 虚拟模块,
于是插件开始 扫描 → 交给 Tailwind 核心 → 生成一段 CSS → 塞回页面。
这条语句本身不拉文件、也不含样式,
纯粹是 “嘿,Tailwind,可以开工了” 的触发口令。
这是让大部分人误解的地方:
看到@import "tailwindcss"就是觉得,这不就是导入了tailwindcss预设了的一堆样式字典嘛,就跟bootstrap或者layui一样!这就给我造成困惑 那@tailwindcss/vite干啥的,而且为啥每次看head中关于tailwindcss的样式集合预设还不一样?
@source
这个是取代v3版本,tailwind-config的content字段的,用来标记tailwind的扫描范围的(默认情况下哎之扫描当前项目,如果是多仓库那子项目中的tailwind部分就不会被扫描到。旦“被 Tailwind 扫描到”就会被tailwind构建(一些tailwind专属语法比如 @theme @apply 等)输出和生效了。
需要注意的是哪怕你当前项目的css文件显示@import了其它模块里的含tailwind语法的css文件,但是只要此css文件没有被当前项目扫描到,那么其中的tailwind语法是不会被tailwind构建输出的。必须显式的指定扫描到子项目!
/* shared-styles.css */
.some-component {@apply bg-blue-500 p-4; /* 这里的 @apply 需要被扫描到才会生效 */
}/* main.css */
@import "./shared-styles.css"; /* ❌ 这样不会让 Tailwind 扫描 shared-styles.css */
@import "tailwindcss";/* 必须在 @source 中显式包含 */
@source "./shared-styles.css"; /* ✅ 这样才会扫描其中的 Tailwind 语法 */