befly-vite
v1.28.0
Published
Befly Vite 配置预设和插件集合
Readme
befly-vite
befly-vite 是 Befly 后台项目的 Vite 预设包,负责把项目约定、常用插件和 Vite 原生配置组合在一起。
它目前提供 4 类能力:
- Vite 配置侧的
createBeflyViteConfig() - Vite 配置侧的
scanViews() - 浏览器运行时的
Layouts() - CLI 入口
befly-vite
适用场景
- 想在后台管理项目里直接复用 Befly 约定的 Vite 默认配置
- 想自动扫描
src/views和befly-admin-ui/views - 想复用 TDesign 相关的自动导入、组件自动注册和图标规则
- 想保留 Vite 原生
viteConfig作为统一扩展出口
安装
bun add -d befly-vite vite如果项目本身还没安装运行时依赖,通常还需要自行安装 Vue 侧依赖,例如:
bun add vue vue-router pinia tdesign-vue-next tdesign-icons-vue-next导出说明
Vite 配置侧
在 vite.config.js 里使用:
import { createBeflyViteConfig, scanViews } from "befly-vite";可用导出:
createBeflyViteConfigscanViews
浏览器运行时
在前端运行时代码里使用:
import { Layouts } from "befly-vite";可用导出:
Layouts
createBeflyViteConfig
createBeflyViteConfig(options) 是主入口,用来生成 Befly 项目的 Vite 配置。
最小用法
// vite.config.js
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig();默认内置内容
调用后默认会包含以下能力:
vue-router/vite路由扫描插件@vitejs/plugin-vueunplugin-vue-components@指向项目srcserver.open = falseserver.hmr = truebuild.outDir = "dist"build.assetsDir = "assets"build.cssMinify = "lightningcss"css.transformer = "lightningcss"- 默认 CSS 浏览器基线:Chrome 107 / Edge 107 / Firefox 104 / Safari 16.0
参数说明
| 参数 | 类型 | 默认值 | 作用 |
| -------------- | -------------------- | --------------- | ---------------------------------------------------- |
| root | string | process.cwd() | 项目根目录,用于解析 src、扫描 views 和生成别名 |
| devtool | boolean | false | 是否启用 vite-plugin-vue-devtools |
| analyzer | boolean | false | 是否启用打包分析,并输出到 <root>/temp/analyzer |
| resolvers | Object \| Object[] | undefined | 追加到组件自动注册中的自定义 resolver |
| manualChunks | Function \| Object | undefined | 便捷写入 build.rolldownOptions.output.manualChunks |
| viteConfig | Object | {} | 最终合并到默认配置上的 Vite 原生配置 |
参数细节
root
root 决定这些行为的基准目录:
@别名指向哪个srcscanViews()扫哪个项目目录- 打包分析文件输出到哪个
temp
最常见写法:
import { fileURLToPath } from "node:url";
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
root: fileURLToPath(new URL(".", import.meta.url))
});devtool
开启后会额外注入 vite-plugin-vue-devtools。
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
devtool: true
});适合:本地调试组件树、路由和状态。
analyzer
开启后会额外注入 vite-bundle-analyzer,并把报告输出到项目的 temp/analyzer。
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
analyzer: true
});适合:分析打包体积、依赖拆分和大包来源。
resolvers
befly-vite 默认内置:
- TDesign Vue Next resolver
- TDesign 图标 resolver
src/**/*.vue、node_modules/befly-admin-ui/**/*.vue、packages/adminUI/**/*.vue(monorepo 本地源码)都会进入组件自动注册范围
如果项目还想增加额外 resolver,可以通过 resolvers 追加。它会同时追加到:
unplugin-vue-components
import { createBeflyViteConfig } from "befly-vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
export default createBeflyViteConfig({
resolvers: [ElementPlusResolver()]
});说明:
- 默认的 TDesign resolver 不会被替换,只会追加新的 resolver
- 如果你传单个对象,也会自动转成数组处理
manualChunks
manualChunks 是一个便捷入口,会写入 build.rolldownOptions.output.manualChunks。
适合:
- 只想快速传一个
manualChunks - 不想为了简单分包额外展开完整的
build配置
如果还要同时配置 output.entryFileNames、chunkFileNames、assetFileNames 等其他构建输出项,推荐直接走 viteConfig.build.rolldownOptions。
如果旧项目还在传 viteConfig.build.rollupOptions,在 Vite 8 下也还能继续工作;只是新配置更建议直接写 build.rolldownOptions。
函数写法:
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
manualChunks: function (id) {
if (id.includes("tdesign-vue-next")) {
return "tdesign";
}
if (id.includes("node_modules")) {
return "vendor";
}
}
});对象写法:
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
manualChunks: {
vue: ["vue", "vue-router", "pinia"],
tdesign: ["tdesign-vue-next", "tdesign-icons-vue-next"]
}
});适合:
- 把大依赖稳定拆分出去
- 减少首屏主包体积
- 提升缓存命中率
viteConfig
viteConfig 是扩展出口,所有不值得再额外封装一层的配置,都建议直接从这里传入。
简单示例:
import { createBeflyViteConfig } from "befly-vite";
import { fileURLToPath } from "node:url";
export default createBeflyViteConfig({
root: fileURLToPath(new URL(".", import.meta.url)),
viteConfig: {
server: {
port: 5600
}
}
});适合放在这里的配置包括:
server.portserver.proxydefinebuild.sourcemapbuild.cssTargetcss.lightningcssbuild.rolldownOptions- 其他任意 Vite 原生配置
chunks 的推荐方式:
- 简单场景用顶层
manualChunks - 需要完整控制输出结构时,用
viteConfig.build.rolldownOptions
示例:
import { createBeflyViteConfig } from "befly-vite";
import { fileURLToPath } from "node:url";
export default createBeflyViteConfig({
root: fileURLToPath(new URL(".", import.meta.url)),
viteConfig: {
build: {
rolldownOptions: {
output: {
manualChunks: function (id) {
if (id.includes("tdesign-vue-next") || id.includes("tdesign-icons-vue-next")) {
return "tdesign";
}
if (id.includes("node_modules/vue") || id.includes("node_modules/vue-router") || id.includes("node_modules/pinia")) {
return "framework";
}
},
entryFileNames: "assets/[name]-[hash].js",
chunkFileNames: "assets/[name]-[hash].js"
}
}
}
}
});CSS 兼容配置
befly-vite 不再提供单独的 compat 配置,CSS 兼容统一走 Vite 8 原生配置。
默认行为
默认内置:
{
build: {
cssTarget: ["chrome107", "edge107", "firefox104", "safari16"],
cssMinify: "lightningcss"
},
css: {
transformer: "lightningcss",
lightningcss: {
targets: {
chrome: 107 << 16,
edge: 107 << 16,
firefox: 104 << 16,
ios_saf: 16 << 16,
safari: 16 << 16
}
}
}
}为什么同时有 build.cssTarget 和 css.lightningcss.targets
build.cssTarget控制 CSS 压缩输出目标css.lightningcss.targets控制 Lightning CSS 的语法降级和前缀处理目标
这两者默认保持一致。
项目侧覆盖写法
如果项目需要更高或更低的兼容基线,可以直接通过 viteConfig 覆盖。
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
viteConfig: {
build: {
cssTarget: ["chrome120", "edge120", "firefox120", "safari17"]
},
css: {
lightningcss: {
targets: {
chrome: 120 << 16,
edge: 120 << 16,
firefox: 120 << 16,
ios_saf: 17 << 16,
safari: 17 << 16
},
drafts: {
nesting: true
}
}
}
}
});说明:
viteConfig.build.cssTarget一旦传入,会直接覆盖默认值viteConfig.css.lightningcss.targets一旦传入,也会直接覆盖默认值- 其他
css.lightningcss选项仍会与默认配置合并
常见 CSS 配置案例
只改压缩目标
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
viteConfig: {
build: {
cssTarget: "safari16"
}
}
});调整 Lightning CSS draft 能力
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
viteConfig: {
css: {
lightningcss: {
drafts: {
nesting: true,
customMedia: true
}
}
}
}
});关闭 CSS 压缩
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
viteConfig: {
build: {
cssMinify: false
}
}
});路由扫描规则
befly-vite 内部通过 scanViews(appRoot) 扫描视图目录,并交给 vue-router/vite。
默认扫描来源
<root>/src/views<root>/node_modules/befly-admin-ui/views
其中 befly-admin-ui/views 会被挂到 core/ 前缀下。
默认排除规则
两个目录都会排除:
**/components/**单独使用 scanViews
如果项目要直接复用这套扫描规则,也可以单独调用:
import { fileURLToPath } from "node:url";
import { scanViews } from "befly-vite";
const appRoot = fileURLToPath(new URL(".", import.meta.url));
const routesFolders = scanViews(appRoot);
console.log(routesFolders);返回值结构示例:
[
{
src: "/absolute/path/to/src/views",
path: "",
exclude: ["**/components/**"]
},
{
src: "/absolute/path/to/node_modules/befly-admin-ui/views",
path: "core/",
exclude: ["**/components/**"]
}
];组件自动注册规则
befly-vite 现在只负责 Vue 组件自动注册,不再自动导入 Vue、Pinia、Vue Router API。页面和组件里用到这些 API 时,需要显式 import。
Components
默认会对以下目录启用组件自动注册:
src/**/*.vuenode_modules/befly-admin-ui/**/*.vue
默认内置 resolver:
- TDesign Vue Next resolver
tdesign-icons-vue-next图标 resolver- 你额外传入的
resolvers
说明:
src/components会被作为本地组件目录扫描befly-vite只自动注册组件;Vue、Pinia、Vue Router API 仍需按项目规范手动导入
Layouts
Layouts(routes, rootRedirectPath, resolveLayoutComponent) 用于浏览器运行时把 auto-routes 结果转换成带布局的最终路由。
作用
它会根据页面文件名里的 _数字 后缀决定使用哪个布局,并把普通路径段统一转换成短横线小写。
例如:
userCenter/account_1.vue->/user-center/account,布局1newsDetail_2.vue->/news-detail,布局2guide/index_1.vue->/guide,布局1
基础示例
import { Layouts } from "befly-vite";
const routes = [
{
path: "userCenter",
children: [
{
path: "account_1",
component: () => import("./views/userCenter/account.vue")
},
{
path: "my_news",
component: () => import("./views/userCenter/my_news.vue")
}
]
}
];
const finalRoutes = Layouts(routes, "/dashboard", function (layoutName) {
return layoutName ? `layout:${layoutName}` : "layout:default";
});参数说明
| 参数 | 类型 | 作用 |
| ------------------------ | ---------- | --------------------------------------------- |
| routes | Array | auto-routes 产出的原始路由数组 |
| rootRedirectPath | string | 根路径 / 的重定向目标;传空值则不注入重定向 |
| resolveLayoutComponent | Function | 根据布局名返回布局组件 |
Layouts 规则说明
- 动态参数段如
:userId会保留原样 - 普通路径段会统一转成短横线小写
- 下划线
_会转成- - 驼峰会转成短横线小写
_数字后缀只用于布局名,不会出现在最终路径里index子页会折叠成父路径下的空子路径
CLI
包内自带 befly-vite 命令,本质上是一个 Bun 环境下的 Vite 启动包装器,用来帮项目找到 vite/bin/vite.js 并转发参数。
最常见脚本写法
页面项目自己的 package.json 在这里主要只保留运行脚本;在 Befly 仓库内,lint / format 的配置文件、根脚本和提交钩子统一跟随仓库根 oxfmt.config.js / oxlint.config.ts 与共享 Oxc 基线,不要在基于 befly-vite 的页面包里再复制第二套可执行 Oxc 配置。
{
"scripts": {
"dev": "bunx --bun befly-vite",
"build": "bunx --bun befly-vite build",
"preview": "bunx --bun befly-vite preview"
}
}作用
- 自动定位
vite可执行文件 - 用 Bun 转发执行
vite - 保持页面项目运行脚本写法统一
- 让页面包把
dev/build/preview和lint/format的职责边界分开:运行脚本留在页面包,代码规范跟随根配置
完整案例
案例 1:最小后台项目
import { fileURLToPath } from "node:url";
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
root: fileURLToPath(new URL(".", import.meta.url))
});案例 2:本地开发端口 + 调试工具
import { fileURLToPath } from "node:url";
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
root: fileURLToPath(new URL(".", import.meta.url)),
devtool: true,
viteConfig: {
server: {
port: 5206
}
}
});案例 3:打包分析 + Vite 原生分包
import { fileURLToPath } from "node:url";
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
root: fileURLToPath(new URL(".", import.meta.url)),
analyzer: true,
viteConfig: {
build: {
rolldownOptions: {
output: {
manualChunks: function (id) {
if (id.includes("tdesign-vue-next") || id.includes("tdesign-icons-vue-next")) {
return "tdesign";
}
if (id.includes("node_modules")) {
return "vendor";
}
}
}
}
}
}
});案例 4:自定义 CSS 浏览器兼容目标
import { fileURLToPath } from "node:url";
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
root: fileURLToPath(new URL(".", import.meta.url)),
viteConfig: {
build: {
cssTarget: ["chrome120", "edge120", "firefox120", "safari17"]
},
css: {
lightningcss: {
targets: {
chrome: 120 << 16,
edge: 120 << 16,
firefox: 120 << 16,
ios_saf: 17 << 16,
safari: 17 << 16
}
}
}
}
});案例 5:Vite 原生能力扩展
import { fileURLToPath } from "node:url";
import { createBeflyViteConfig } from "befly-vite";
export default createBeflyViteConfig({
root: fileURLToPath(new URL(".", import.meta.url)),
viteConfig: {
define: {
__APP_NAME__: JSON.stringify("befly-admin")
},
build: {
sourcemap: true
},
server: {
proxy: {
"/api": {
target: "http://127.0.0.1:3000",
changeOrigin: true
}
}
}
}
});什么时候应该直接用 viteConfig
如果某个能力本身已经是稳定的 Vite 原生配置,而且 befly-vite 没必要再包装一层,优先直接用 viteConfig。例如:
server.portserver.proxydefinebuild.sourcemapbuild.cssTargetbuild.cssMinifycss.lightningcssresolve.alias
License
Apache-2.0
