多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

boneyard-js 骨骼屏生成框架实战指南:DOM 快照转矩形 Bones 的多框架 Skeleton 方案

boneyard-js 骨骼屏生成框架实战指南:DOM 快照转矩形 Bones 的多框架 Skeleton 方案 【免费下载链接】boneyardAuto generated skeleton loading framework项目地址https://gitcode.com/gh_mirrors/bo/boneyard点击查看免费下载导读本文以 boneyard 仓库中《Boneyard Skeleton Skill》文档为主体系统讲解boneyard-js——一个把真实 UI 快照成带定位矩形 bones骨骼的骨架屏生成器。你将掌握bones 数据格式与解析优先级、boneyard.config.json全部配置项、CLI 构建与 Vite 插件工作流、React/Svelte/Vue/Angular/Preact/React Native 多框架接入方式以及一套可直接照做的调试检查清单。读完即可为项目接入像素级还原真实布局的骨架屏无需手写任何描述符。一、架构总览从真实 DOM 到骨架矩形boneyard-js的核心思想是快照真实渲染后的 UI将其转换为绝对定位的矩形占位元素。所有核心源码位于 packages/boneyard/文件职责src/react.tsxReact 的Skeleton组件同时导出configureBoneyard、registerBones、BoneSuspensesrc/preact.tsxPreact 原生集成无需 compat 层src/Skeleton.svelteSvelte 5 组件src/Skeleton.vueVue 组件src/angular.tsAngular 组件src/native.tsx、src/react-native.tsxReact Native 支持src/extract.tssnapshotBones()DOM 遍历器、fromElement()描述符提取器src/shared.tsbones 注册表、动画常量SHIMMER/PULSE/DEFAULTS、resolveResponsivesrc/types.tsSnapshotConfig、Bone、CompactBone、ResponsiveBones等类型定义src/runtime.ts非 React 场景的 vanillarenderBones()src/layout.ts描述符驱动的compileDescriptor/computeLayout布局引擎bin/cli.jsCLI 入口boneyard-js build多框架导出入口根据 packages/boneyard/package.json 的 exports 字段包提供多种子路径全部共享同一套 bones 数据与动画常量boneyard-js— 导出snapshotBones、renderBones、fromElement、computeLayout等核心 API见 src/index.tsboneyard-js/react—Skeleton、registerBones、configureBoneyardboneyard-js/preact—Skeleton、registerBones、configureBoneyardboneyard-js/native—Skeleton、registerBones、configureBoneyardReact Nativeboneyard-js/svelte—Skeleton组件、registerBonesboneyard-js/vue—Skeleton组件、registerBones、configureBoneyardboneyard-js/angular—SkeletonComponent、registerBones、configureBoneyardboneyard-js/vite—boneyardPlugin()Vite 插件二、Bones 数据格式与解析优先级2.1 紧凑数组格式snapshotBones()产出或 CLI 写入*.bones.json的是紧凑数组[x%, y_px, w%, h_px, borderRadius, isContainer?]x和w是相对于容器宽度的百分比y和h是像素值borderRadius可以是数字px或字符串如50%第 6 个可选元素isContainer真值标记容器骨骼——它在渲染时会被跳过。容器骨骼代表父级背景若与子骨骼同时渲染会产生透明度叠加。在 src/types.ts 中CompactBone被定义为 5 元或 6 元元组normalizeBone()负责把紧凑元组校验长度必须为 5 或 6并归一化为结构化Bone对象同时兼容resolveJsonModule下从 JSON 导入时被收窄为数组的类型情况。仓库示例 packages/boneyard/src/bones/sidebar-nav.bones.json 展示了结构化形式每个断点下包含name、viewportWidth、width、height与bones数组例如{ x: 8, y: 9, w: 28, h: 28, r: 50% }即一个圆形头像骨骼。2.2 骨骼解析优先级Skeleton在运行时按以下优先级获取骨骼数据React 实现见 src/react.tsx 的initialBones ?? getRegisteredBones(name)显式传入的initialBonesprop优先级最高按name在注册表中查找来自registry.js由registerBones注入底层是 src/shared.ts 的Mapstring, RegisteredBonesFixture 兜底——仅在 CLI 构建模式window.__BONEYARD_BUILD true下生效。2.3 响应式断点选择多断点 bones 由ResponsiveBones{ breakpoints: Recordnumber, SkeletonResult }表示。resolveResponsive()见 src/shared.ts实现就近匹配把所有断点键升序排序后从大到小找到第一个width bp的断点若没有命中则回退到最小断点。Skeleton默认用容器实测宽度container-query 式行为来选择断点也可通过select: viewport改用window.innerWidth——这与 CLI 按视口宽度建档的方式一致适合应用壳布局容器窄于窗口的场景。三、动画常量与暗色模式3.1 动画常量单一事实来源所有框架实现都从 src/shared.ts 导入动画常量保证跨框架行为一致SHIMMER { angle: 110, start: 30, end: 70, speed: 2s, lightHighlight: #f7f7f7, darkHighlight: #2c2c2c } PULSE { speed: 1.8s, lightAdjust: 0.3, darkAdjust: 0.02 } DEFAULTS { web: { light: #f0f0f0, dark: #222222 }, native: { light: #f0f0f0, dark: #222222 } }SHIMMER扫光动画的角度110°、渐变的起止位置30%→70%、时长2s及明暗两套高光色PULSE呼吸动画时长 1.8slightAdjust/darkAdjust是adjustColor()在明暗模式下对基色做提亮的系数源码中adjustColor(color, amount)同时支持rgba()与#hex两种颜色输入见 src/shared.tsCONTAINER容器骨骼专用的调色系数adjustment: 0.12/darkAdjustment: 0.03。adjustColor是动画实现的关键底层函数pulse 动画在0%/100%用基色、50%用adjustColor(基色, 0.3)生成高亮帧React 中以keyframes bp-${uid}内联样式注入见 src/react.tsx。3.2 暗色模式检测暗色模式通过html或任意祖先元素上的.dark类检测Tailwind 标准约定不使用prefers-color-scheme把控制权明确交给应用开发者。当.dark存在时启用darkColor与darkShimmerColor。React 实现用MutationObserver监听html的 class 变化、并监听matchMedia((prefers-color-scheme: dark))事件用于 OS 主题切换触发祖先.dark变化的场景见 src/react.tsx。四、SnapshotConfig控制骨骼提取的四个开关snapshotConfig以 prop 形式传给Skeleton或作为snapshotBones()的第三个参数类型定义见 src/types.ts{ leafTags?: string[] // 视为原子骨骼的标签与默认值合并p,h1-h6,li,td,th captureRoundedBorders?: boolean // 捕获带边框圆角但无背景的元素默认: true excludeTags?: string[] // 完全跳过这些标签 excludeSelectors?: string[] // 跳过匹配 CSS 选择器的元素 }leafTags与默认集合合并而非替换。默认集合在 src/extract.ts 定义为p, h1-h6, li, td, th。命中 leafTags 的节点被当作单块扁平骨骼不再递归其子节点captureRoundedBorders默认true。在 src/extract.ts 中容器只要满足背景色非透明 / 有背景图 / 有可见边框且圆角之一即判定为有视觉表面hasVisualSurface从而产出容器骨骼。这正是白色卡片bg-white rounded-xl border也能被捕获的原理——每个背景色都算数白卡也是卡excludeTags/excludeSelectors命中的元素连同所有后代一起跳过src/extract.ts 中直接return不递归。excludeSelectors支持任意合法 CSS 选择器类、ID、属性、标签及组合选择器如.card .badge。底层snapshotBones()的遍历逻辑src/extract.ts值得一提读取每个可见元素的getComputedStyle跳过display:none、visibility:hidden、opacity:0图片/表单元素img/svg/video/canvas/input/button/textarea/select一律视为叶子叶子骨骼取getBoundingClientRect()的精确像素位置x/w换算为相对根元素的百分比y/h保持像素近正方形的媒体元素宽高差 4px自动得到50%圆角适配 SVG 图标、圆形头像表格节点tr/td/th/thead/tbody/table强制r: 0避免与overflow:hidden父级冲突。五、配置文件boneyard.config.json 全参数详解boneyard.config.json是首要定制点同时控制 CLI 构建与运行时默认值。运行时选项会通过configureBoneyard()烘焙进生成的registry.js。完整示例{ breakpoints: [375, 768, 1280], out: ./src/bones, wait: 800, color: #e5e5e5, darkColor: #2a2a2a, animate: shimmer, shimmerColor: #ebebeb, darkShimmerColor: #333333, speed: 2s, shimmerAngle: 110, stagger: false, transition: false, boneClass: , resolveEnvVars: true, auth: { cookies: [{ name: session, value: env[SESSION_TOKEN], domain: localhost }], headers: { Authorization: Bearer env[API_TOKEN] } } }5.1 构建期选项Key默认值说明breakpoints[375, 768, 1280]CLI 捕获的视口宽度可自动探测 Tailwind 断点out./src/bones输出目录wait800页面加载后等待的毫秒数再开始捕获5.2 运行时选项烘焙进 registry.jsKey默认值说明color#f0f0f0骨骼填充色亮色模式darkColor#222222骨骼填充色暗色模式.dark类animatepulse动画pulse、shimmer或solidshimmerColor#f7f7f7Shimmer 高光色亮色模式darkShimmerColor#2c2c2cShimmer 高光色暗色模式speed2sshimmer/ 1.8spulse动画时长shimmerAngle110Shimmer 渐变角度度staggerfalse骨骼间动画延迟毫秒数true 80mstransitionfalse加载结束时的淡出过渡毫秒数true 300msboneClass—应用到每个骨骼元素的 CSS 类5.3 认证与会话支持auth配置让 CLI/Vite 插件能携带 Cookie 与请求头访问登录态页面支持env[VAR_NAME]占位符配合resolveEnvVars: true从.env与process.env解析缺失时警告并解析为空串避免静默发送坏 token。Vite 插件的实现细节见 src/vite.tsCookie 会通过白名单ALLOWED_COOKIE_KEYS过滤请求头会拦截host、content-length等危险头。此外插件还支持cdp选项直连已有 Chrome 调试端口复用用户浏览器里的真实登录态src/vite.ts。5.4 优先级组件级 props 配置文件经configureBoneyard() src/shared.ts 包默认值。CLI 标志flags对构建期选项会覆盖配置文件。React 端configureBoneyard({...})会把配置合并进全局globalConfig见 src/react.tsx组件 props 再覆盖之。六、实战任务接入、Fixture、排除与 CLI6.1 给组件添加骨架屏import { Skeleton } from boneyard-js/react Skeleton namemy-component loading{isLoading} MyComponent data{data} / /Skeleton运行时loading{true}时展示骨骼层loading{false}时展示真实 children骨骼层以绝对定位覆盖层渲染并通过aria-busy与data-boneyard-*属性保持可访问性与可调试性见 src/react.tsx。6.2 使用 Fixture构建期无真实数据时Skeleton namemy-component loading{isLoading} fixture{MyFixture /} snapshotConfig{{ leafTags: [section] }} MyComponent data{data} / /Skeleton关键模式在 fixture 中用section或任意自定义标签作为叶子元素再把该标签加入leafTags提取器就会把每个 section 当作单块扁平骨骼处理不再递归其子元素。fixture只在 CLI 设置window.__BONEYARD_BUILD true时渲染src/react.tsx 的构建模式分支fixture ?? children。6.3 排除不需要捕获的元素方式一标记属性nav>Skeleton snapshotConfig{{ excludeSelectors: [.icon, svg], excludeTags: [nav] }}6.4 CLI 命令速查# 自动探测开发服务器 npx boneyard-js build # 显式 URL 输出目录 npx boneyard-js build http://localhost:PORT --out src/bones # 强制全量重建跳过 hash 检查 npx boneyard-js build --force # Watch 模式HMR 时重新捕获 npx boneyard-js build --watch # 自定义断点 npx boneyard-js build --breakpoints 375,640,768,1024,1280,1536 # React Native 模式 npx boneyard-js build --native --out ./bones6.5 Vite 插件免第二个终端若项目使用 Vite可直接接入boneyardPlugin()src/vite.tsdev server 启动即执行首次捕获之后每次 HMR 变更在 1.5s 防抖后自动重新捕获并生成/合并.bones.json与registry.*。插件支持out、breakpoints、wait、routes、skipInitial、cdp、debug等选项且配置文件的优先级低于插件显式选项。其底层逻辑与 CLI 一致注入__BONEYARD_BUILD true、遍历[data-boneyard]标记、按data-boneyard-config读取 snapshotConfig、调用window.__BONEYARD_SNAPSHOT即snapshotBones完成捕获。七、Skeleton Props 完整参考Prop类型默认值说明loadingboolean必填显示骨架还是 childrenchildrenReactNode必填真实内容namestring必填注册表 key CLI 标识initialBonesResponsiveBones—预生成骨骼覆盖注册表colorstring#f0f0f0骨骼填充色亮色模式任意 CSS 颜色hex、rgba、hsl 等darkColorstring#222222暗色模式骨骼填充色.dark类任意 CSS 颜色animateAnimationStylepulsepulse、shimmer、solid也接受 booleantruepulse、falsesolidstaggernumber \| booleanfalse交错延迟true80mstransitionnumber \| booleanfalse淡出时长true300msboneClassstring—每个骨骼的 CSS 类classNamestring—容器类fallbackReactNode—loading 且无骨骼时显示fixtureReactNode—供 CLI 捕获的 mock 内容snapshotConfigSnapshotConfig—控制骨骼提取selectcontainer \| viewportcontainer断点选择的宽度基准React 还额外提供BoneSuspensesrc/react.tsx与 React 的Suspense模型配合对使用useSuspenseQuery或React.lazy的组件在挂起时自动展示Skeleton loading构建模式下会把 children 包进Suspense避免挂起查询导致提取崩溃--wait窗口内查询自然 resolve 后快照真实 DOM。八、调试检查清单骨架屏完全不显示检查应用入口是否导入了registry.js且存在对应name的 bones JSON骨骼过多 / 出现内部形状在snapshotConfig中添加leafTags后重建骨骼与布局不匹配用--force从当前 DOM 重新生成断点选错检查容器宽度——骨骼使用就近的断点匹配暗色模式未生效boneyard 依赖html或祖先上的.dark类不使用prefers-color-schemeCLI 找不到骨架组件需要loading{false}或有 fixture让真实 UI 渲染出来供捕获透明度叠加 / 双重渲染容器骨骼c: true应在渲染时被跳过——如果出现叠加说明过滤逻辑缺失各框架实现均通过normalizeBone(raw).c过滤见 src/react.tsx 与 src/runtime.tsShimmer 不可见检查shimmerColor与color的对比度——默认是#f0f0f0上的#f7f7f7。九、延伸无 DOM 环境的描述符方案除浏览器快照路径外包还提供描述符驱动的布局引擎src/layout.ts与 vanilla 运行时renderBones()src/runtime.tsfromElement()把渲染后的 DOM 提取为SkeletonDescriptor含 display/flex/gap/padding/aspectRatio/font/text 等结构化字段compileDescriptorcomputeLayout用编译缓存与文本测量在任意容器宽度下计算骨骼位置渲染期无需 DOM适用于 SSR、Worker、边缘函数等场景skeleton(el)是提取→计算→渲染的一站式便捷函数src/index.ts。这两条路径与浏览器快照路径共享同一套 bones 格式与动画常量是理解 boneyard 完整能力边界的补充。十、最小落地三步走构建npx boneyard-js build或接入boneyardPlugin()按需在boneyard.config.json中调整断点、动画、认证接线在应用入口导入生成的registry.js自动调用registerBones注册所有 bones JSON包裹Skeleton namemy-component loading{isLoading}按 name 自动解析骨骼必要时用initialBones、fixture、snapshotConfig精确控制提取行为。整个过程无需手写布局描述boneyard 直接读取浏览器已计算好的像素位置天然做到像素级还原真实 UI这也是其零布局偏移zero-layout-shift能力的基础。赞分享【免费下载链接】boneyardAuto generated skeleton loading framework项目地址https://gitcode.com/gh_mirrors/bo/boneyard点击查看免费下载相关推荐Boneyard 骨架屏框架开发指南从真实 UI 快照提取 bones到 CLI 构建、配置与多框架落地Boneyard 骨架屏框架开发指南从真实 UI 快照提取 bones到 CLI 构建、配置与多框架落地 Boneyard 是一款以快照真实 UI 为骨架boneyard从真实 UI 自动提取像素级骨架屏的跨框架方案boneyard从真实 UI 自动提取像素级骨架屏的跨框架方案 boneyard 是一套自动生成骨架屏skeleton loading screen的工程TABAnimatediOS原生骨架屏加载框架TABAnimatediOS原生骨架屏加载框架 1. 项目基础介绍及编程语言 TABAnimated 是一个为 iOS 开发者提供的原生骨架屏加载框架。该框架移动开发UI组件上一篇Voyager 全平台安装指南商店一键安装、手动抢鲜包与 Safari 原生扩展部署详解下一篇FoundationDB 本地开发环境搭建指南从 macOS 安装、状态验证到首个事务应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表