尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Docs 定制化完全指南:运行时主题、脚本注入与主题定制文件实战解析

Docs 定制化完全指南:运行时主题、脚本注入与主题定制文件实战解析 Docs 定制化完全指南运行时主题、脚本注入与主题定制文件实战解析【免费下载链接】docsDocs is an open-source text editor: web-native, made for real-time collaboration, cleanly structured documents and sub-documents with full ownership of your data. Built to scale with Django and React.项目地址: https://gitcode.com/GitHub_Trending/docs150/docsDocs 作为一款基于 Django React 构建的开源协同文档编辑器为部署者提供了三层渐进式的定制能力通过FRONTEND_CSS_URL/FRONTEND_JS_URL实现零代码的运行时主题与行为注入通过THEME_CUSTOMIZATION_FILE_PATH指向的 JSON 主题定制文件实现图标、页脚、翻译、Waffle 服务网格等品牌化配置。本文将以官方定制指南 documentation/customization.md 为骨架结合后端settings.py、配置接口ConfigView与前端ConfigProvider的源码实现给出完整可落地的配置方案与参数说明。读完本文你将掌握如何在不停机、不重新构建的前提下为 Docs 更换品牌皮肤与注入自定义脚本如何通过一份 JSON 文件统一配置站点图标、多语言页脚、界面文案翻译与 Waffle 服务网格并理解这些配置从前端请求到后端加载的完整链路。一、定制化能力全景与工作机制Docs 的定制化体系可以分为两条主线运行时注入Runtime Injection通过FRONTEND_CSS_URL与FRONTEND_JS_URL两个环境变量指向自托管的 CSS / JS 文件 URL。前端应用启动后会以link relstylesheet和script标签的方式动态加载它们无需任何代码改动或重新编译适合快速换肤、注入第三方分析脚本、挂载自定义菜单等场景。主题定制文件Theme Customization File通过THEME_CUSTOMIZATION_FILE_PATH指向一份 JSON 文件集中配置header.icon头部图标、footer页脚、translations翻译覆盖、waffle服务网格、favicon、home、help、onboarding等结构化选项由后端在启动/运行时读取并提供给前端。两条主线的配置最终都会汇聚到同一个入口前端启动时请求GET /api/v1.0/config/获取公共配置再交由ConfigProvider分发消费。这也是理解 Docs 定制化架构的关键配置值在服务端定义经配置 API 下发由前端运行时应用因此绝大部分定制都不需要重启前端或重新构建镜像。二、运行时主题定制FRONTEND_CSS_URL2.1 配置方法在 Docs 后端运行环境中设置环境变量将其指向一个可公开访问的 CSS 文件地址FRONTEND_CSS_URLhttp://anything/custom-style.css设置后Docs 前端会在页面head中注入link relstylesheet href...加载该样式表并应用到整个前端应用。从源码看该变量在 settings.py 中被定义为可空配置项FRONTEND_CSS_URL values.Value( None, environ_nameFRONTEND_CSS_URL, environ_prefixNone )未设置时该值为None前端不会注入任何外部样式表行为与默认一致。2.2 前端如何加载在 ConfigProvider.tsx 中前端通过 Next.js 的Head组件注入样式链接{conf?.FRONTEND_CSS_URL ( Head link relstylesheet href{conf?.FRONTEND_CSS_URL} / /Head )}也就是说只要配置接口返回的FRONTEND_CSS_URL非空样式表就会被插入页面头部并按照 CSS 层叠规则覆盖默认样式。该配置字段同样出现在ConfigResponse类型定义中见 useConfig.tsx。2.3 典型用例自定义背景色假设你想将整个应用的背景色替换为品牌色可以创建一份自定义 CSS 文件并托管到任意静态服务器body { background-color: #3498db; }然后设置FRONTEND_CSS_URL指向该文件。应用加载后背景色即被覆盖为#3498db。由于是运行时加载你可以随时替换 CSS 内容并在刷新后生效无需重启任何服务。2.4 优势与适用边界零代码定制不需要修改或重新构建前端仓库灵活换肤可用任意 CSS 规则打造符合组织品牌的主题运行时生效修改 CSS 文件内容即可热切换主题无需重启或重新编译。需要注意的是运行时 CSS 覆盖的是样式层而非组件层它能改变颜色、尺寸、布局等外观但如果要调整 DOM 结构或交互行为则需要配合下一节的 JavaScript 注入。三、运行时 JavaScript 注入FRONTEND_JS_URL3.1 配置方法与 CSS 类似设置环境变量指向一个可公开访问的 JS 文件FRONTEND_JS_URLhttp://anything/custom-script.jsDocs 前端会用 Next.js 的Script组件以afterInteractive策略加载该脚本见 ConfigProvider.tsx{conf?.FRONTEND_JS_URL ( Script src{conf?.FRONTEND_JS_URL} strategyafterInteractive / )}afterInteractive表示脚本在页面完成水合hydration后执行适合注入交互增强类逻辑。对应后端配置定义见 settings.py。3.2 典型用例向头部注入自定义菜单官方文档给出的示例脚本会在应用头部追加一个自定义菜单按钮。脚本需要等待 DOM 就绪后再操作确保目标元素存在(function() { use strict; function initCustomMenu() { // Wait for the page to be fully loaded const header document.querySelector(header); if (!header) return false; // Create and inject your custom menu const customMenu document.createElement(div); customMenu.innerHTML buttonCustom Menu/button; header.appendChild(customMenu); console.log(Custom menu added successfully); return true; } // Initialize when DOM is ready if (document.readyState loading) { document.addEventListener(DOMContentLoaded, initCustomMenu); } else { initCustomMenu(); } })();设置FRONTEND_JS_URL指向该文件后刷新页面即可在头部看到自定义菜单。同样的思路可以用于接入第三方埋点、注入辅助工具条、修改现有功能行为等覆盖样式无法触及的动态定制需求。3.3 优势与边界动态定制无需代码改动即可修改行为与外观高度灵活可新增功能、改造既有特性或集成第三方服务运行时注入无需重启或重新编译。边界提醒注入脚本在浏览器端执行属于运行时增强而非后端逻辑修改涉及数据面或权限面的功能仍需在 Django 后端实现同时该脚本应具备幂等性避免重复加载导致重复插入 DOM。四、主题定制文件核心机制THEME_CUSTOMIZATION_FILE_PATH图标、页脚、翻译与 Waffle 配置都依托于同一套机制主题定制文件Theme Customization File。这是理解 Docs 品牌化定制的钥匙。4.1 环境变量与默认值THEME_CUSTOMIZATION_FILE_PATHpath后端定义见 settings.pyTHEME_CUSTOMIZATION_FILE_PATH values.Value( os.path.join(BASE_DIR, impress/configuration/theme/default.json), environ_nameTHEME_CUSTOMIZATION_FILE_PATH, environ_prefixNone, ) THEME_CUSTOMIZATION_CACHE_TIMEOUT values.IntegerValue( 60 * 60 * 24, environ_nameTHEME_CUSTOMIZATION_CACHE_TIMEOUT, environ_prefixNone, )要点默认路径BASE_DIR/impress/configuration/theme/default.json即仓库中的 src/backend/impress/configuration/theme/default.json。该文件是 Docs 出厂默认的主题定制内容。缓存超时默认86400秒1 天。主题定制 JSON 会被缓存修改文件后最长可能需要一个缓存周期才会被重新读取或清空缓存后立即生效。若将该变量设为空字符串后端会返回空的主题定制对象{}见 viewsets.py。4.2 后端加载链路与缓存策略主题定制文件由ConfigView._load_theme_customization()加载见 viewsets.py完整流程如下若THEME_CUSTOMIZATION_FILE_PATH未设置直接返回{}以文件路径的 slug 生成缓存键theme_customization_slug先查 Django 缓存缓存未命中则用utf-8编码读取 JSON 文件并json.load解析若文件不存在FileNotFoundError或 JSON 非法JSONDecodeError记录 error 日志并返回{}不会导致服务崩溃解析成功后写入缓存缓存时长为THEME_CUSTOMIZATION_CACHE_TIMEOUT。这套容错设计意味着一个损坏或缺失的定制文件只会让定制项失效为默认值而不会拖垮整个配置接口相关行为也被后端测试覆盖见 test_api_config.py 中针对不存在文件与非法 JSON 的用例。4.3 配置下发GET /api/v1.0/config/ConfigView是一个AllowAny权限、带config节流作用域的公开接口见 viewsets.py。它把FRONTEND_CSS_URL、FRONTEND_JS_URL、FRONTEND_THEME、LANGUAGES等公共设置打包返回并附上theme_customization即主题定制文件解析结果与RELEASE_VERSIONdict_settings[theme_customization] self._load_theme_customization() dict_settings[RELEASE_VERSION] settings.RELEASE return drf.response.Response(dict_settings)前端通过 getConfig 请求config/并缓存到localStorage键docs_config随后useConfig以 5 分钟 staleTime 的 TanStack Query 持有该配置。前端ThemeCustomization接口见 useConfig.tsx声明了以下可用键键类型用途favicon{ light, dark }浅色/深色模式站点图标link relicon属性footerFooterType页脚配置支持多语言 default兜底headerHeaderType头部图标/Logo 配置help对象帮助文档 URL、支持邮箱、法务链接home对象首页配置如with-proconnect、icon-banneronboarding对象新手引导开关与链接translationsResourcei18next 翻译资源覆盖waffleLaGaufreV2PropsWaffleLa Gaufre服务网格ConfigProvider在拿到配置后分别处理应用翻译覆盖、设置主题、注入 CSS/JS、设置 Sentry/PostHog、处理 favicon 与版本刷新逻辑见 ConfigProvider.tsx。五、自定义 Docs 头部图标header.icon头部图标可以从主题定制文件中配置。以仓库自带的开发环境示例 src/helm/env.d/dev/configuration/theme/demo.json 为例{ header: { logo: {}, icon: { src: /assets/icon-docs.svg, style: { width: 32px, height: auto }, alt: , withTitle: true } } }字段说明src图标资源路径可指向仓库静态资源如/assets/icon-docs.svg或任意可访问的 URLstyle行内样式控制图标的渲染尺寸如width/heightalt无障碍替代文本withTitle是否连同产品标题一起展示header.logoLogo 配置示例中为空对象表示不启用。该配置是可选的——如果主题定制文件中没有header.icon前端将回退到默认图标。仓库中的默认文件 src/backend/impress/configuration/theme/default.json 使用的即是/assets/icon-docs.svg宽高 40px。六、页脚配置footer页脚同样来自主题定制文件且支持按语言分发的完整配置结构。6.1 配置结构{ footer: { default: { logo: { src: /assets/icon-docs.svg, width: 54px, alt: Docs Logo, withTitle: true }, externalLinks: [ { label: GitHub, href: https://github.com/suitenumerique/docs/ }, { label: DINUM, href: https://www.numerique.gouv.fr/dinum/ }, { label: ZenDiS, href: https://zendis.de/ }, { label: BlockNote.js, href: https://www.blocknotejs.org/ } ], bottomInformation: { label: Unless otherwise stated, all content on this site is under, link: { label: licence etalab-2.0, href: https://github.com/etalab/licence-ouverte/blob/master/LO.md } } }, en: { legalLinks: [ { label: Legal Notice, href: # }, { label: Personal data and cookies, href: # }, { label: Accessibility, href: # } ], bottomInformation: { label: Unless otherwise stated, all content on this site is under, link: { label: licence MIT, href: https://github.com/suitenumerique/docs/blob/main/LICENSE } } }, fr: { ...: 同结构法语文案 }, de: { ...: 同结构德语文案 }, nl: { ...: 同结构荷兰语文案 } } }6.2 关键规则footer.default是语言不匹配时的兜底配置当用户当前语言在footer中没有对应键如en/fr/de/nl时前端会回退到footer.default保证任何语言环境下页脚都不会空白legalLinks法务链接组法律声明、隐私与 Cookie、无障碍声明等可在各语言块内独立配置externalLinks页脚展示的外部链接列表labelhref成对出现bottomInformation页脚底部信息支持label文本 内嵌link文本与地址。官方文档同时给出了配置后的视觉效果示例见 documentation/assets/footer-configurable.png配置正确后页脚会按所选语言展示对应的法律链接与版权信息。七、自定义翻译translationsDocs 的界面文案可以部分覆盖——即基于现有翻译资源仅对需要改动的键做增量覆盖而不必维护整份语言文件。7.1 配置方法在主题定制文件中加入translations键结构遵循 i18next 资源格式{ translations: { en: { translation: { Docs: MyDocs, New doc: } } } }顶层键是语言代码如en、fr、zh-CN等语言下再套一层translation内部是原始文案键 → 自定义文案值的映射未覆盖的键继续使用内置翻译因此这是一种部分覆盖机制。7.2 前端如何应用在 ConfigProvider.tsx 中配置返回后调用customizeTranslations()将覆盖资源合并进当前 i18next 实例useEffect(() { if (!conf?.theme_customization?.translations) { return; } customizeTranslations(conf.theme_customization.translations); }, [conf?.theme_customization?.translations, customizeTranslations]);该逻辑位于features/language模块与 Docs 的同步语言机制配合当用户语言确定后覆盖翻译会即时生效无需刷新页面。7.3 实战提示文案键必须与前端实际使用的 i18n key 完全一致包括大小写与空格例如示例中的Docs、New doc可通过源码中的useTranslation()调用点确认键名由于翻译是前端 i18next 资源覆盖范围受限于前端已声明的键无法凭空新增翻译命名空间多语言场景下为每个语言代码各写一份translation块即可实现按语言的品牌化文案。八、WaffleLa Gaufre配置waffleWaffle法语俗称 La Gaufre即华夫饼是 Docs 中展示**服务网格services grid**的小部件典型用于把同一组织内的多个服务入口聚合到一个下拉/弹层网格中方便用户在不同服务间跳转。8.1 配置方法在主题定制文件中使用waffle键结构对齐前端 UI 组件库的LaGaufreV2Props。参考仓库示例 src/helm/env.d/dev/configuration/theme/demo.json{ waffle: { data: { services: [ { name: Docs, url: https://docs.numerique.gouv.fr/, maturity: stable, logo: https://lasuite.numerique.gouv.fr/assets/products/docs.svg }, { name: Visio, url: https://visio.numerique.gouv.fr/, maturity: stable, logo: https://lasuite.numerique.gouv.fr/assets/products/visio.svg }, { name: Fichiers, url: https://fichiers.numerique.gouv.fr/, maturity: stable, logo: https://lasuite.numerique.gouv.fr/assets/products/fichiers.svg } ] }, showMoreLimit: 9 } }8.2 可用属性LaGaufreV2Propswaffle的值直接对应前端 UI 组件库LaGaufreV2的 props可在前端依赖gouvfr-lasuite/ui-components的LaGaufreV2.tsx中查看完整定义常见属性包括属性说明data.services静态服务列表每个服务包含name、url、maturity、logo等字段showMoreLimit网格中直接展示的服务数量上限超出部分收进更多折叠区示例为 9apiUrl动态获取服务的数据接口地址8.3 行为规则官方文档明确了 Waffle 的两种数据来源行为静态模式如果提供了data.servicesWaffle 直接展示这些服务不发起额外请求动态模式如果不提供data可以通过apiUrl属性从后端 API 端点动态拉取服务列表。按需二选一内部服务清单固定时用静态配置如上例服务由中台系统统一管理、需要实时变更时用apiUrl动态获取。九、完整示例与实战清单9.1 开箱即用的演示配置仓库为 Helm 开发环境提供了完整的主题定制示例 src/helm/env.d/dev/configuration/theme/demo.json它一次性覆盖了本文讲到的全部能力translations把 Docs 文案替换为 MyDocs、把 New doc 替换为 footerdefaulten/fr/de/nl四语言页脚header.icon自定义头部图标waffle静态展示 Docs / Visio / Fichiers 三个服务额外还包含home首页 ProConnect 开关与横幅图标与favicon浅色/深色图标。9.2 上线前的检查清单文件可达确认THEME_CUSTOMIZATION_FILE_PATH指向的文件在容器/后端进程内真实存在且可被读取建议先手动执行python -c import json;json.load(open(path))验证 JSON 合法性缓存预期主题定制 JSON 默认缓存 1 天THEME_CUSTOMIZATION_CACHE_TIMEOUT上线后想立即生效可调小该值或清空缓存配置接口验证部署后请求GET /api/v1.0/config/检查theme_customization是否按预期返回资源可访问FRONTEND_CSS_URL、FRONTEND_JS_URL以及图标/Logo 引用的资源地址必须对浏览器端可访问注意 CSP、跨域与鉴权策略回退安全任何一项配置异常文件缺失、JSON 非法、字段缺失都会优雅回退到默认值不会阻断应用启动——这由后端_load_theme_customization的容错分支保证版本一致性ConfigProvider会比对前后端RELEASE_VERSION不一致时自动触发一次刷新确保定制配置与新版本代码匹配。9.3 配置链路速查环境变量FRONTEND_CSS_URL / FRONTEND_JS_URL / THEME_CUSTOMIZATION_FILE_PATH ... │ ▼ Django settings.py 定义与解析src/backend/impress/settings.py │ ▼ GET /api/v1.0/config/ → ConfigView 组装公共设置 加载主题定制 JSONsrc/backend/core/api/viewsets.py#L3086-L3167带缓存 │ ▼ 前端 useConfig 拉取并缓存到 localStoragesrc/frontend/apps/impress/src/core/config/api/useConfig.tsx │ ▼ ConfigProvider 分发注入 CSS/JS、应用翻译、设置主题/favicon、初始化 Analyticssrc/frontend/apps/impress/src/core/config/ConfigProvider.tsx通过这条链路Docs 将品牌化定制从代码层剥离到了配置层无论是部署在裸机、Docker Compose 还是 Kubernetes/Helm对应模板见 src/helm/impress/templates只需调整环境变量与主题定制 JSON即可在不改动一行业务代码的前提下完成整套视觉与行为定制。【免费下载链接】docsDocs is an open-source text editor: web-native, made for real-time collaboration, cleanly structured documents and sub-documents with full ownership of your data. Built to scale with Django and React.项目地址: https://gitcode.com/GitHub_Trending/docs150/docs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表