ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Vant CLI 组件库目录结构完全指南:从源码组织到构建产物

Vant CLI 组件库目录结构完全指南:从源码组织到构建产物 Vant CLI 组件库目录结构完全指南从源码组织到构建产物【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant导读本文基于 packages/vant-cli/docs/directory.zh-CN.md 展开系统讲解基于 Vant CLI 搭建组件库时的标准目录规范从源码目录、单个组件的组织方式到执行build命令后生成的es/lib双格式产物再到类型声明文件的自动生成。读完本文你将能按官方规范组织组件库代码、理解两种组件编写方式SFC 与 JS/CSS 分离的取舍并彻底看懂构建产物中每个文件style/index.js、[name].min.js、index.d.ts等的来源与用途。一、源码目录结构基于 Vant CLI 搭建的组件库其基本目录结构如下project ├─ src # 组件源代码 │ ├─ button # button 组件源代码 │ └─ dialog # dialog 组件源代码 │ ├─ docs # 静态文档目录 │ ├─ home.md # 文档首页 │ └─ changelog.md # 更新日志 │ ├─ vant.config.mjs # Vant CLI 配置文件 ├─ package.json └─ README.md各目录职责明确src/组件源码的根目录每个子目录对应一个组件。在真实仓库中例如 packages/vant/src/button 目录存放了 Button 组件的Button.tsx、index.less、index.ts、types.ts、demo/与test/等文件docs/静态文档目录其中的home.md作为文档站点首页、changelog.md作为更新日志。它们会被 Vant CLI 的文档站点编译流程见 packages/vant-cli/src/compiler/compile-site.ts转换为可浏览的站点页面vant.config.mjsVant CLI 的核心配置文件组件库的名称、入口、构建选项等均在此声明详细字段说明参见 packages/vant-cli/docs/config.zh-CN.md。二、单个组件的目录结构单个组件的目录如下button ├─ demo # 示例目录 │ └─ index.vue # 组件示例 ├─ index.vue # 组件源码 └─ README.md # 组件文档其中demo/index.vue组件的演示示例构建文档站点时会被渲染为可交互的示例页面index.vue或index.tsx组件实现源码Vant 仓库中的组件即大量使用 TSX 编写例如 packages/vant/src/button/Button.tsxREADME.md组件文档可同时提供README.zh-CN.md中英文双版本例如 packages/vant/src/button/README.zh-CN.md。三、两种组件编写方式SFC 与 JS/CSS 分离Vant CLI 同时支持两种组件源码组织方式它们的差异直接决定构建产物形态与主题定制能力。3.1 使用 .vue 单文件组件SFC使用.vue文件编写组件时构建阶段会将 SFC 拆解并编译生成对应的 JS 和 CSS 文件且JS 文件中会自动引入 CSS 文件——这意味着使用者只需引入 JS 即可同时获得样式。这一行为可以在 packages/vant-cli/src/compiler/compile-sfc.ts 的源码中得到印证compileSfc通过vue/compiler-sfc解析模板、脚本与样式三个块随后调用injectStyle将编译后的样式文件以import ./xxx-sfc.css;的形式注入脚本头部再输出为同名的.js与.css文件。此外该文件还负责渲染函数注入将模板编译出的render函数重命名后挂载到组件对象上injectRenderScoped 样式支持对包含 scoped 样式的组件基于源码内容计算scopeIddata-v-xxx实现样式隔离TS 编译处理生成类型为 TS 的脚本时会在首行追加// ts-nocheck注释因为编译生成的 render 函数缺少类型定义详见 compile-sfc.ts。3.2 使用独立的 JS 与 CSS 文件如果需要将 JS 和 CSS 解耦以实现主题定制等功能则需要在编写代码时就使用独立的 JS 和 CSS 文件结构如下button ├─ demo # 组件示例 │ └─ index.vue # 组件示例入口 ├─ index.js # 组件入口 ├─ index.less # 组件样式可以为 less 或 scss └─ README.md # 组件文档采用这种目录结构时组件库的使用者需要分别引入 JS 和 CSS 文件。它的核心价值在于通过引入样式源文件less 或 scss并修改样式变量可以实现主题定制功能。因为构建产物中保留了未编译的样式源文件入口详见下文单个组件编译后的目录中的style/less.js使用者可以覆盖 Less/Sass 变量来整体定制主题这是 SFC 方式样式被编译为固定 CSS 并内联进 JS难以做到的。四、构建结果目录运行build命令后Vant CLI 会在es和lib目录下生成可用于生产环境的组件代码。这两个目录对应两套主流模块规范结构如下project ├─ es # es 目录下的代码遵循 esmodule 规范 │ ├─ button # button 组件编译后的代码目录 │ ├─ dialog # dialog 组件编译后的代码目录 │ └─ index.js # 引入所有组件的入口 (ESModule) │ └─ lib # lib 目录下的代码遵循 commonjs 规范 ├─ button # button 组件编译后的代码目录 ├─ dialog # dialog 组件编译后的代码目录 ├─ index.js # 引入所有组件的入口 ├─ index.less # 所有组件未编译的样式入口 ├─ index.css # 打包后的组件样式用于 CDN 引入 ├─ [name].js # 打包后的组件脚本UMD 格式 ├─ [name].es.js # 打包后的组件脚本ESModule 格式 ├─ [name].min.js # 打包和压缩后的组件脚本UMD 格式 └─ [name].es.min.js # 打包和压缩后的组件脚本ESModule 格式各产物的用途可归纳为文件模块规范用途es/index.jsESModule现代打包工具Vite、Webpack 等按需引入的入口lib/index.jsCommonJSNode.js 环境或旧构建链路的入口lib/index.less—全部组件未编译样式入口供主题定制链路使用lib/index.css—打包后的完整组件样式适合通过 CDN 直接引入[name].js/[name].min.jsUMD通过script标签全局引入含压缩版[name].es.js/[name].es.min.jsESModule浏览器原生 ESM 引入含压缩版4.1 打包产物的生成原理[name].js等打包产物的格式并非硬编码而是由 Vant CLI 调用 Vite 的库模式构建生成且支持通过vant.config.mjs中的build.bundleOptions定制。默认配置见 packages/vant-cli/src/compiler/compile-bundles.tsconst DEFAULT_OPTIONS: BundleOption[] [ { minify: false, formats: [umd] }, { minify: true, formats: [umd] }, { minify: false, formats: [es, cjs], external }, ];其中external取自package.json中的dependencies即第三方依赖不会被打进产物而是作为外部依赖由使用者自行解析从而避免组件库重复打包 React/Vue 等运行时依赖。4.2 单个组件编译后的目录单个组件编译后的目录结构如下button ├─ index.js # 组件编译后的 JS 文件 ├─ index.css # 组件编译后的 CSS 文件 ├─ index.less # 组件编译前的 CSS 文件可以为 less 或 scss └─ style # 按需引入样式的入口 ├─ index.js # 按需引入编译后的样式 └─ less.js # 按需引入未编译的样式可用于主题定制style/index.js 与 style/less.js 的来源这两个按需样式入口由 packages/vant-cli/src/compiler/gen-component-style.ts 为每个组件自动生成style/index.js按需引入编译后的 CSS.css文件style/less.js按需引入未编译的 Less/Sass 源文件供主题定制使用。当项目配置了build.css.removeSourceFile: true时该文件不会生成源码中通过vantConfig.build?.css?.removeSourceFile ! true判断。样式按需引入的核心是组件样式依赖分析。genStyleDepsMap见 packages/vant-cli/src/compiler/gen-style-deps-map.ts会解析每个组件入口的依赖图找出其依赖的其他组件例如 Button 内部使用到 Icon并在引入本组件样式时顺带引入依赖组件的样式。分析结果以style-deps.json的形式保存随后genComponentStyle会依据依赖顺序生成import xxx.css;ESM 侧与require(xxx);CJS 侧的入口文件保证按需引入时样式不会缺漏。而lib/index.less全量未编译样式入口则由 packages/vant-cli/src/compiler/gen-package-style.ts 根据依赖分析得到的组件顺序以import语句聚合所有组件的样式源文件生成。4.3 build 命令的完整流水线es/lib两套产物并不是一次性拷贝生成的而是经过一条串行流水线。以 packages/vant-cli/src/commands/build.ts 中的tasks数组为例build命令依次执行Copy Source Code将src/整体拷贝到es/与lib/两份副本Build Package Script Entry生成es/index.js与lib/index.js全量入口其中包含install安装函数与组件version字段见 gen-package-entry.tsBuild Component Style Entry生成各组件style/index.js、style/less.js按需样式入口Build Package Style Entry生成lib/index.less全量样式入口Build Type Declarations若存在tsconfig.declaration.json则执行tsc -p生成类型声明详见下文第五节Build ESModule Outputs对es/副本做 ESM 规范的脚本/样式编译并删除demo/、test/等非产物目录Build CommonJS Outputs对lib/副本做 CommonJS 规范编译Build Bundled Outputs调用 Vite 生成[name].js等 UMD/ESM 打包产物。组件入口index.js的生成逻辑同样值得关注gen-package-entry.ts 会读取vant.config.mjs中build.namedExport是否命名导出与build.skipInstall跳过注册的组件列表配置扫描src/下所有组件生成包含import、install注册函数与export语句的入口文件——这也是目录结构即组件清单这一约定在构建层面的具体落地。五、生成类型声明当组件库使用 TypeScript 编写且根目录下存在tsconfig.declaration.json文件时Vant CLI 会在构建阶段自动生成.d.ts类型声明文件对应build.ts中检测tsConfig文件存在后执行tsc -p tsconfig.declaration.json的逻辑。tsconfig.declaration.json的参考格式如下{ extends: ./tsconfig.json, compilerOptions: { declaration: true, declarationDir: ., emitDeclarationOnly: true }, include: [es/**/*, lib/**/*], exclude: [node_modules, **/test/**/*, **/demo/**/*] }各配置项的作用extends继承项目基础tsconfig.json的编译选项避免重复配置declaration: true开启声明文件生成declarationDir: .声明文件输出到被编译目录的对应位置确保es/button/index.d.ts、lib/button/index.d.ts等与产物文件一一对应emitDeclarationOnly: true只输出声明文件不重复输出 JS因为 JS 已由 Vant CLI 的构建流程负责include仅对es/与lib/两份产物目录生成声明exclude跳过node_modules、test、demo等无需暴露类型的目录。仓库中 Vant 主包的 packages/vant/tsconfig.declaration.json 即采用了这一结构并在exclude中额外加入了**/vue-lazyload/*等无需生成声明的子模块。成功生成类型声明后需要在package.json中添加类型入口声明让 TypeScript 与 IDE 能够自动找到类型定义{ typings: lib/index.d.ts }此后使用者在import该组件库时即可获得完整的类型提示与编译期校验。六、小结一张图读懂目录规范至此可以总结出 Vant CLI 组件库目录规范的核心脉络源码期src/按组件分目录每个组件包含demo/、组件源码SFC 或 JSCSS与README.mddocs/承载静态文档vant.config.mjs声明构建配置构建期build命令将src/复制为es/ESModule与lib/CommonJS两份产物分别完成脚本/样式编译、按需样式入口与全量样式入口生成、类型声明生成以及 UMD/ESM 打包产物生成消费期现代打包工具走es/按需引入含style/样式入口CDN/全局脚本走[name].js系列产物主题定制走index.less与style/less.js未编译样式源文件链路。掌握这套目录规范后无论是从零搭建组件库可参考 packages/create-vant-cli-app 脚手架还是维护、扩展现有组件都能快速定位源码、理解构建产物并正确配置发布信息。【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进