
Scalar 客户端渲染实战用 scalar/client-side-rendering 生成静态 API 文档 HTML【免费下载链接】scalarScalar is an open-source API platform: Modern REST API Client Beautiful API References ✨ 1st-Class OpenAPI/Swagger Support项目地址: https://gitcode.com/GitHub_Trending/sc/scalar本文围绕 Scalar 开源仓库中的scalar/client-side-rendering包展开深入讲解如何仅凭一个函数调用就在服务端生成加载 Scalar API Reference 的完整静态 HTML 页面包括 ESM/UMD 两种构建产物的选择逻辑、CSP nonce 安全配置、函数型配置的序列化方案以及这些能力在 Astro、Docusaurus 等集成中的真实落地方式。读完本文你将能在任何不依赖 Node 运行时依赖的场景下快速产出可部署的 API 文档页面并理解其底层实现原理。一、这个包解决什么问题Scalar 官方文档客户端渲染与包描述都指出scalar/client-side-rendering的定位是使用 CDN 将 Scalar API Reference 渲染为静态 HTML无需服务端依赖。从 package.json 可以看到它的依赖只有三个内部包scalar/schemas、scalar/types、scalar/validation构建产物是一个纯 ESM 模块。也就是说你不需要在服务端引入庞大的 Vue 组件树或运行 API Reference 本体只需要在构建期调用一个渲染函数把一段带脚本的 HTML 字符串写进响应或页面浏览器加载后由 CDN 上的scalar/api-reference独立完成渲染。核心入口由 src/index.ts 导出export { type AnyApiReferenceConfiguration, DEFAULT_CDN, DEFAULT_ESM_CDN, type HtmlRenderingConfiguration, getConfiguration, getScriptTags, renderApiReference, serializeConfigToJs, } from ./html-rendering其中renderApiReference是最高层的 APIgetScriptTags、getConfiguration、serializeConfigToJs则是被各框架集成复用的底层构件。二、最小可用示例三步产出完整 HTML安装npm install scalar/client-side-rendering包要求 Node.js22见 package.json 的engines字段。渲染一个页面import { renderApiReference } from scalar/client-side-rendering const html renderApiReference({ pageTitle: My API Reference, config: { url: https://registry.scalar.com/scalar/apis/galaxy?formatjson, }, })返回的html是一份完整的 HTML 文档。从 html-rendering.ts 的模板可以看到其结构head中包含title默认为Scalar API Reference、charset、viewport元信息若传入了nonce会额外输出meta propertycsp-nonce content… /若配置了customCss或自定义主题会内联style typetext/cssbody中有一个div idapp/div挂载点之后是加载与初始化脚本。默认加载 ESM 构建renderApiReference生成的脚本由 getScriptTags 负责。默认情况下不传cdn、nonce、bundle输出的是代码分割的现代 ESM 构建script typemodule import { createApiReference } from https://cdn.jsdelivr.net/npm/scalar/api-reference/esm.js createApiReference(#app, { url: ... }) /script测试 html-rendering.test.ts 验证了这条默认路径产物包含!doctype html、默认标题、div idapp/div以及import ... from .../esm.js的模块脚本。为什么默认选择 ESM因为它是代码分割的浏览器只下载当前页面真正需要的懒加载 chunk而不是整个庞大的 UMD 单体包从而减少阻塞首次渲染的 JavaScript 体积见 CHANGELOG.md 中 0.4.0 的说明。三、构建产物选择UMD 与 ESM 的取舍两条加载路径包内置两个默认 CDN 常量html-rendering.ts/** 经典 UMD 构建注册 window.Scalar 全局变量通过 script src 加载 */ export const DEFAULT_CDN https://cdn.jsdelivr.net/npm/scalar/api-reference /** 现代 ESM 构建0.4.0 起默认通过 script typemodule 加载 */ export const DEFAULT_ESM_CDN https://cdn.jsdelivr.net/npm/scalar/api-reference/esm.js选择 UMD 的三种方式方式说明cdn: https://...指定 CDN URL例如固定某个版本如https://cdn.jsdelivr.net/npm/scalar/api-reference1.28.11见 Docusaurus 集成类型定义bundle: false使用默认 UMD 构建设置了nonce默认回退严格 nonce 型 CSP 下自动使用 UMD原因见下文加载 UMD 时生成的脚本是两段script srchttps://cdn.jsdelivr.net/npm/scalar/api-reference/script script typetext/javascript Scalar.createApiReference(#app, { url: ... }) /script决策逻辑源码解析getScriptTags中的核心判断一行即可概括html-rendering.tsconst useUmd bundle false || (bundle undefined (cdn ! undefined || Boolean(nonce)))bundle: false→ 强制 UMDbundle: true或字符串 URL → 强制 ESMbundle优先级最高可以覆盖cdn与nonce的回退测试见 html-rendering.test.ts都不传时有cdn或nonce则 UMD否则默认 ESM。固定版本与指定 ESM 地址cdn: https://.../scalar/api-reference1.28.11固定 UMD 版本bundle: https://.../esm.js加载指定的 ESM 构建测试见 html-rendering.test.ts。注意bundle也可能被集成方以未知选项的方式塞进config对象传入renderApiReference会从 config 中读取并剥离它避免它被序列化泄漏到客户端html-rendering.ts测试见 html-rendering.test.ts。四、CSP nonce在严格安全策略下运行自 0.2.0 起包提供了nonce选项用于内容安全策略CSP支持CHANGELOG.mdApiReference({ url: /openapi.json, // 与你的 script-src CSP 指令中的值保持一致 nonce: r4nd0m, })nonce 会被印到哪里当传入nonce时生成的 HTML 会在内联script上打上nonce属性在 CDNscript src标签上打上nonce在 Scalar 自己的style标签上打上nonce额外输出meta propertycsp-nonce content… /供运行时注入样式的独立构建读取html-rendering.ts。这使 API Reference 可以在无unsafe-inline、无unsafe-eval的严格script-src策略下运行。为什么设置了 nonce 就默认用 UMD这是一个容易踩坑的点。ESM 构建通过原生import加载其懒加载 chunk而浏览器无法给import发起的请求附加 nonce因此在严格 nonce 型 CSP 下这些 chunk 会被拦截。而 UMD 是单文件脚本打上 nonce 后不会有后续请求因此成为 nonce 场景的安全默认值html-rendering.ts 与 CHANGELOG.md 中 0.4.0 的说明一致。如果你的 CSP 使用了strict-dynamic或对 CDN 域名做了放行可以传bundle: true强制切回 ESM——测试 html-rendering.test.ts 明确验证了nonce bundle: true仍会输出带 nonce 的模块脚本。style-src 的已知限制需要特别说明style-src仍然需要unsafe-inline。原因在于 API Reference 会渲染大量内联style…属性而 CSP nonce 只能作用于script、style、link这类元素永远无法为内联属性授权。所以 nonce 方案的收益是完全严格的script-src而非全部指令见 CHANGELOG.md 中 0.2.0 的 Note 及 html-rendering.ts 的 JSDoc。安全加固细节nonce 属于攻击者可能影响的输入因此代码在把 nonce 写入属性前做了双重转义html-rendering.tsescapeHtml转义 escapeHtmlAttribute在escapeHtml基础上再编码双引号防止突破属性边界。测试 html-rendering.test.ts 用scriptalert(1)/script验证了注入被拦截。同理pageTitle也会做 HTML 转义测试见 html-rendering.test.ts。五、函数型配置的序列化serializeConfigToJs问题背景JSON 序列化会丢掉函数API Reference 的配置支持大量函数值选项onBeforeRequest、onLoaded、onRequestSent、onSidebarClick、tagsSorter、operationsSorter、generateHeadingSlug等。当配置需要跨进程/跨边界传递时例如 Docusaurus 会把路由 props 做 JSON 序列化JSON.stringify会静默丢弃这些函数——这正是 0.3.0 修复的问题CHANGELOG.md。实现原理serializeConfigToJshtml-rendering.ts把配置序列化成JavaScript 对象字面量而不是 JSON普通属性走JSON.stringify函数属性通过Function.prototype.toString()输出为字面量源码数组内若含函数例如plugins数组用serializeArrayWithFunctions逐项处理。因此onBeforeRequest、请求钩子等回调能在写入内联script或其他会被 JSON 序列化的边界后存活。测试 html-rendering.test.ts 覆盖了十几类函数属性sorters、slug 生成器、各类钩子L415-L439 还验证了plugins数组中函数的保留。使用注意事项从源码注释html-rendering.ts可知函数必须是箭头函数或function表达式对象方法简写如onBeforeRequest(request) {}无法序列化为合法的独立表达式。Docusaurus 集成中的实际应用在 Docusaurus 集成 中插件在 Node 端函数仍存活时先用getConfiguration规范化配置再调用serializeConfigToJs序列化最后把序列化结果作为路由 props 注入import { getConfiguration, serializeConfigToJs } from scalar/client-side-rendering // ... const normalizedConfiguration getConfiguration({ ...configuration, hideDarkModeToggle: true }) addRoute({ path: normalizeUrl([baseUrl, defaultOptions.route ?? /scalar]), component: path.resolve(__dirname, ./ScalarDocusaurus), exact: true, configuration: serializeConfigToJs(normalizedConfiguration), })六、配置规范化getConfiguration在把配置序列化或写入页面之前getConfigurationhtml-rendering.ts做两件事执行函数型的content如果content是函数先调用取回结果裁决content与url冲突只有当url存在时才删除content即优先使用 URL 加载规范内联 content 只在无 URL 时生效。0.1.13 起getConfiguration的签名放宽为接受PartialHtmlRenderingConfiguration消除了集成边界处的Recordstring, unknown强转CHANGELOG.md。三个行为的测试都在 html-rendering.test.ts。七、自定义样式与主题注入renderApiReference的第二个参数是customTheme配合 config 里的customCss、theme由 getStyles 生成内联style传了customCss→ 输出/* Custom CSS */段未设置theme且传了customTheme→ 输出/* Custom Theme */段设置了theme如kepler、purple时自定义主题会被跳过——因为此时主题由 API Reference 运行时加载。测试 html-rendering.test.ts 覆盖了四种组合两者都有、仅有 customCss、仅有 customTheme、theme 存在时排除 customTheme。注意style标签同样会带上 nonce 属性nonce 存在时。八、框架集成中的两种渲染模式Astro 集成ScalarComponent.astro展示了本包在真实框架中的两种用法static模式默认在构建期用renderApiReference提前渲染出完整 HTML 文档嵌入页面的脚本只在硬加载时执行client模式只渲染一个空容器在浏览器端挂载 Scalar并围绕 Astro 视图过渡事件重新挂载——适用于 Starlight 等带客户端导航的站点避免静态脚本在软导航后失效。--- import { renderApiReference, type HtmlRenderingConfiguration } from scalar/client-side-rendering // ... const { cdn, pageTitle, nonce, ...config } finalConfiguration --- {renderMode client ? ( ScalarClient config{config} cdn{cdn} nonce{nonce} / ) : ( div set:html{renderApiReference({ config, cdn, pageTitle, nonce })} / )}同时src/html-rendering.ts 的注释也给出边界需要水合的服务端渲染应使用 server 模块本包定位是纯客户端渲染。九、运行测试验证行为如果你要验证或改造本包行为仓库提供了完整的 Vitest 测试npm test对应 package.json 的scripts.test。测试文件 html-rendering.test.ts 按renderApiReference、getScriptTags、getConfiguration、serializeConfigToJs分组覆盖默认 ESM 输出与三种 UMD 回退路径bundle对cdn/nonce的优先级nonce 的注入、csp-noncemeta 输出与属性注入防护函数配置的保留、函数数组plugins、仅函数配置的合法序列化无前导逗号主题/CSS 的组合逻辑与content/url裁决。结语scalar/client-side-rendering用极小的 API 表面积解决了静态 HTML CDN 加载 API Reference这一高频需求并把几个易错点构建产物选择、CSP nonce、函数序列化封装成了经过测试验证的默认行为。结合 核心实现、测试套件 以及 Astro、Docusaurus 集成你可以在自己的框架中复刻同样的模式构建期渲染 HTML、序列化配置、按安全策略选择构建产物最终输出一个零服务端依赖、可快速部署的 API 文档页面。【免费下载链接】scalarScalar is an open-source API platform: Modern REST API Client Beautiful API References ✨ 1st-Class OpenAPI/Swagger Support项目地址: https://gitcode.com/GitHub_Trending/sc/scalar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考