AEM6.5单页加载多Swagger-UI组件仅渲染一个的问题
多Swagger-UI组件在AEM6.5页面渲染失败的问题与解决
问题场景
在AEM6.5的单个页面中加载多个Swagger-UI组件时,页面仅能渲染一个组件,其余组件已正确加载到DOM但无法显示。即便每个组件使用了唯一ID,仍只有最后一个组件能正常渲染。
原组件模板代码
<sly data-sly-use.model="xxx.aem.component.content.SwaggerModel" data-sly-use.template="core/wcm/components/commons/v1/templates.html" data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html"> </sly> <sly data-sly-call="${clientlib.all @ categories='xxx.ui.swagger-ui'}"/> <sly data-sly-call="${template.placeholder @ isEmpty=!model.defined}"></sly> <div data-sly-test="${model.defined}"> <h1 class="t-title"> ${model.title} </h1> <div id="${model.uniqueId}"></div> <sly data-sly-test="${model.defined}" data-sly-call="${swaggerScript @ path=model.swaggerYamlPath, name=model.swaggerYamlName, dom_id=model.uniqueId}"></sly> </div> <template data-sly-template.swaggerScript="${ @ path, name, dom_id}"> <script> window.onload = function () { window.ui = SwaggerUIBundle({ urls: [ {url: "${path @ context='text'}", name: "${name @ context='text'}"}, ], dom_id: '#${dom_id @ context='text'}', deepLinking: true, filter: true, presets: [ SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset ], plugins: [ SwaggerUIBundle.plugins.DownloadUrl ], layout: 'StandaloneLayout' }); }; </script> </template>
页面DOM示例(问题表现)
<div class="swagger"> <link rel="stylesheet" href="/etc.clientlibs/xxx/clientlibs/static/swagger-ui.min.css" type="text/css"> <script src="/etc.clientlibs/xxx/clientlibs/static/swagger-ui.min.js"></script> <div> <h1 class="t-title"> Here goes the optional title for the Swagger component </h1> <div id="swagger-ui-1671020283"></div> <script> window.onload = function () { window.ui = SwaggerUIBundle({ urls: [ {url: "/content/dam/yaml-files/account-information-service-api-v2-of-fi.yaml", name: "account-information-service-api-v2-of-fi"}, ], dom_id: '#swagger-ui-1671020283', deepLinking: true, filter: true, presets: [ SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset ], plugins: [ SwaggerUIBundle.plugins.DownloadUrl ], layout: 'StandaloneLayout' }); }; </script> </div> </div> <div class="swagger"> <div> <h1 class="t-title"> </h1> <div id="swagger-ui-1110306185"></div> <script> window.onload = function () { window.ui = SwaggerUIBundle({ urls: [ {url: "/content/dam/yaml-files/consent-flow-api-v2-of-fi.yaml", name: "consent-flow-api-v2-of-fi"}, ], dom_id: '#swagger-ui-1110306185', deepLinking: true, filter: true, presets: [ SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset ], plugins: [ SwaggerUIBundle.plugins.DownloadUrl ], layout: 'StandaloneLayout' }); }; </script> </div> </div>
问题原因与解决方案
核心问题
window.onload被覆盖:每个组件的脚本都直接赋值window.onload,而这个事件只能绑定一个回调,后面的赋值会完全覆盖前面的,导致只有最后一个组件的初始化逻辑执行。- ClientLib重复加载:每个组件都调用
clientlib.all,导致Swagger的CSS和JS被重复引入,可能引发资源冲突。 - 全局变量污染:
window.ui被重复赋值,会覆盖之前的Swagger实例引用,同时可能干扰实例正常运行。
修复步骤
1. 移除组件内的ClientLib调用
将<sly data-sly-call="${clientlib.all @ categories='xxx.ui.swagger-ui'}"/>移到页面级模板(比如页面的head或footer区域),确保Swagger资源只加载一次。
2. 替换window.onload为事件监听
使用window.addEventListener('load', ...)代替直接赋值,这样多个回调会被依次执行,不会互相覆盖。
3. 避免全局变量冲突
不要将Swagger实例赋值给全局的window.ui,改用局部变量存储;如果需要全局访问所有实例,可以存入一个全局数组。
修复后的组件模板代码
<sly data-sly-use.model="xxx.aem.component.content.SwaggerModel" data-sly-use.template="core/wcm/components/commons/v1/templates.html"> </sly> <sly data-sly-call="${template.placeholder @ isEmpty=!model.defined}"></sly> <div data-sly-test="${model.defined}"> <h1 class="t-title"> ${model.title} </h1> <div id="${model.uniqueId}"></div> <sly data-sly-test="${model.defined}" data-sly-call="${swaggerScript @ path=model.swaggerYamlPath, name=model.swaggerYamlName, dom_id=model.uniqueId}"></sly> </div> <template data-sly-template.swaggerScript="${ @ path, name, dom_id}"> <script> // 使用addEventListener保证多个回调都能执行 window.addEventListener('load', function () { // 局部变量存储实例,不污染全局作用域 const swaggerInstance = SwaggerUIBundle({ urls: [ {url: "${path @ context='text'}", name: "${name @ context='text'}"}, ], dom_id: '#${dom_id @ context='text'}', deepLinking: true, filter: true, presets: [ SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset ], plugins: [ SwaggerUIBundle.plugins.DownloadUrl ], layout: 'StandaloneLayout' }); // 可选:全局存储所有实例,方便后续操作 if (!window.swaggerInstances) { window.swaggerInstances = []; } window.swaggerInstances.push(swaggerInstance); }); </script> </template>
额外优化建议
- 确认使用的Swagger-UI版本支持多实例渲染(官方标准版本支持该特性)
- 可将Swagger初始化逻辑封装为全局函数,组件仅传递参数调用,提升代码可维护性
内容的提问来源于stack exchange,提问作者scura s
相关产品推荐
相关产品推荐

