# g3soft-libs G3Soft 技术基础设施:**自研 Vue 3 组件库** + **Docus 技术文档站**(面向整体技术体系,不限于前端),pnpm monorepo 管理。 ## 目录结构 ``` g3soft-libs/ ├── pnpm-workspace.yaml # workspace 声明 + catalog 统一版本 + 构建脚本白名单 ├── packages/ │ ├── ui/ # 组件库(发布到 npm 私库) │ │ ├── src/button/ # 一组件一目录 │ │ └── vite.config.ts # 产出 ESM + 类型声明 │ └── tokens/ # 设计变量,组件库与文档站共用 ├── docs/ # 文档站(private,不发布) │ ├── nuxt.config.ts # Docus Layer + alias 直连 packages 源码 │ ├── content/ # Markdown 内容:组件正文 + 手写 API 表格 │ ├── examples/ # 可运行示例,一个功能一个文件,按组件分目录 │ └── app/components/content # Demo.vue(可在 md 中直接使用) ``` ## 环境要求 - Node.js >= 20.19 - pnpm 11(`better-sqlite3` 是 Docus 全文搜索依赖的原生模块,已在 `allowBuilds` 中放行) ## 安装 ```bash pnpm install ``` ## 开发 ```bash pnpm dev ``` 启动技术文档站:端口默认从 3000 起,被占用时自动向后选空闲端口(见 `docs/scripts/dev.mjs`);控制台会打印本机(`http://localhost:`)与局域网访问地址。组件源码通过 alias 直连,改 `packages/ui` 会即时热更。 ## 构建 ```bash pnpm build # 构建 packages/*(组件库产出 dist) pnpm build:docs # 构建文档站静态文件 ``` 文档站静态产物在 `docs/.output/public`,可直接部署到任意静态托管。 ### 改完组件库,怎么让业务方生效 `g3soft-erp` 通过 `overrides` link 到本仓库的 `packages/ui`,**消费的是构建产物 `dist/`**(`exports` 指向 `./dist/index.js` 与 `./dist/style.css`),不是源码。所以改了 `packages/ui/src` 之后不重新 build,业务方一点变化都看不到。 关键在于**不能边跑 ERP dev server 边构建**。ERP 的 Vite 监视着 `dist/`,而 `vite build` 会先清空再逐个写回产物文件,于是: 1. 每个产物文件被重写都触发一次 `page reload`,浏览器反复刷新; 2. 构建中途 `dist/style.css` 会**短暂不存在**,而 ERP 的 `src/styles/index.scss` 里有 `@use '@g3soft/ui/style.css';`,Sass 解析时文件已经没了 —— dev server 进程直接崩溃: ``` [vite] Internal server error: [sass] ENOENT: no such file or directory, open 'D:\workspace\code\g3soft-libs\packages\ui\dist\style.css' ╷ 9 │ @use '@g3soft/ui/style.css'; │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ╵ src\styles\index.scss 9:1 root stylesheet ``` 随后是 `ELIFECYCLE Command failed with exit code 4294967295.` 还有更隐蔽的一种:server 没崩,但缓存到了**写入中途**的模块图,页面白屏、控制台报 `Failed to resolve import "./tooltip/Tooltip.js" from ".../dist/index.js"`。此时 `dist` 盘上的产物其实是完整的,问题纯粹在 Vite 缓存。 **因此顺序只能是「先停、再构建、后启动」**: 1. 停掉 ERP 的 dev server(占用 5090 端口) 2. 在本仓库执行 `pnpm --filter @g3soft/ui build` 3. 在 `g3soft-erp/web` 下执行 `pnpm dev` 重新启动 若怀疑是缓存问题(白屏、找不到模块),额外删掉 `g3soft-erp/web/node_modules/.vite` 再启动即可。改 `packages/tokens` 同理 —— 它也要 build,且要在业务方 dev server 停掉时做。 > 这跟 `pnpm dev`(文档站)无关:文档站通过 alias 直连 `packages/ui/src`,改源码即时热更,不需要也不应该为它重新构建组件库。 ### 部署到子路径 文档站支持挂载到子路径,构建时通过环境变量指定: ```bash NUXT_APP_BASE_URL=/docs/ pnpm build:docs ``` ## 发布组件包 组件库走 changesets 管理版本: ```bash pnpm changeset # 记录本次改动 pnpm version # 生成版本号与 CHANGELOG pnpm release # 构建并发布到私库 ``` `packages/ui` 的 `prepublishOnly` 会执行 `publint` 校验包结构(`exports`、`files` 是否自洽)。 ## 两条链路为什么互不干扰 | | 文档站 | 组件包 | |---|---|---| | 是否发布 | 否(`private: true`) | 是(npm 私库) | | 版本管理 | 无 | changesets(已 `ignore: ["@g3soft/docs"]`) | | 构建命令 | `pnpm build:docs` | `pnpm build` | | 产物 | `docs/.output/public`(静态) | `packages/ui/dist`(ESM + d.ts) | | 依赖边界 | Docus / Nuxt / Tailwind 只在 `docs` 包 | 只有 `vue`(peer) 与 `@g3soft/tokens` | 关键点:Nuxt 相关的依赖**只出现在 `docs/package.json`**,组件库的依赖树里没有任何文档站的东西;changesets 的 `ignore` 保证打 tag 发版时不会带上文档站。 ## 约定 - 组件样式**不写 `scoped`**,用 `g3-` 前缀 + BEM,颜色尺寸一律引用 `--g3-*` 变量。 - 组件 API 文档**手写在 md 里**(Props / Events / Slots / 类型定义 / 样式变量 / 实现说明);改了 props/events/slots 记得同步改文档。 - 示例放 `docs/examples/<组件名>/<示例名>.vue`,在 md 中用 `::demo{name="<组件名>/<示例名>"}` 引用;**一个功能一个示例**,示例里不要在 setup 顶层用 `window` / `document`(文档站是 SSR 预渲染)。