視覺內容片段 — 隨發佈URL傳遞 visual-content-fragments-deliver-with-the-publish-url

當以一或多個附加HTML範本的模型為基礎的內容片段發佈時,該片段的演算HTML可在具有此結構的URL中透過Adobe Experience Manager (AEM) as a Cloud Service發佈層提供:

https://publish-p<programId>-e<envId>.adobeaemcloud.com/adobe/stable/previewtemplates/contentFragments/<templateId>/<fragmentId>/<variation>.html

此URL傳回可內嵌於任何Web內容中的​獨立HTML檔案 (包括內嵌CSS和結構)。

NOTE
視覺內容片段目前可用性有限。
如果您想要參與,請將您的正式電子郵件地址傳送至experience-production-agent@adobe.com

內嵌技術 — 概觀 embedding-techniques-overview

從主機頁面上的視覺內容片段使用HTML有三種不同的方法。 每一個都隨附風格隔離、版面配置行為、協助工具及複雜性的不同特性。

內嵌元素
iframe
自訂元素+陰影DOM
機制
fetch() URL,透過innerHTML將回應HTML插入<div>
<iframe src="publishURL">
定義自訂元素fetch() HTML,插入附加的影子DOM根中
樣式隔離
無 — 片段CSS洩漏至主機頁面,而主機CSS影響片段
完整 — 分開的瀏覽內容,完成CSS隔離
強 — 陰影DOM邊界區塊主控CSS重疊顯示;片段樣式保持封裝狀態
配置參與率
完整 — 內容是正常檔案流程的一部分,會回應Flexbox/格線/容器大小調整
無 — iframe有固定維度;需要明確的width/height或JS式自動調整大小
完整 — 自訂元素會像任何其他DOM元素一樣參與主機檔案的正常流程
協助工具(a11y)
最佳 — 內容位於主要DOM樹狀結構中,可供熒幕閱讀程式和輔助技術完全遍歷
稽核 — 個別的瀏覽內容可能會混淆熒幕助讀程式導覽;需要title屬性
良好 — 內容位於同一份檔案中;陰影DOM可由現代輔助技術穿越
SEO
差 — 透過JS fetch()載入的內容並未被大多數爬蟲編制索引
差 — iframe內容通常不會在上層頁面內容中編制索引
差 — 與內嵌相同;JS擷取的內容不可編目
JavaScript執行階段
共用 — 相同的視窗/檔案內容;如果片段包含<script>標籤,有指令碼衝突的風險
獨立 — 獨立的視窗內容;沒有衝突風險
共用 — 相同的視窗內容,但DOM範圍;陰影根目錄中的指令碼會在主機內容中執行
跨來源支援
發佈URL上需要CORS標頭(服務會設定這些)
原生運作 — iframe載入跨原始內容而不使用CORS
發佈URL上需要CORS標頭(與內嵌相同)
實作複雜性
最小 — 幾行JS
一般 — 不需要任何JS;純HTML
低 — 自訂元素定義約20行JS,可跨頁面重複使用
最適合
建立原型、信任的相同來源內容、版面整合至關重要的內容以及CSS衝突可供管理的內容
快速內嵌、沙箱化內容、無法使用CORS的跨原始案例、必須完全隔離的內容
生產使用 — 平衡隔離、版面參與和協助工具(建議用於AEM核心元件和外部網站)

內嵌元素(擷取+ innerHTML) inline-element-fetch-and-innerhtml

最簡單的方法:

  1. 擷取發佈URL
  2. 將HTML插入容器元素

內嵌元素嵌入的範例:

<div id="cf-container"></div>
<script>
  fetch("<publish-url>")
    .then(r => r.ok ? r.text() : Promise.reject(r.status))
    .then(html => {
      document.getElementById("cf-container").innerHTML = html;
    })
    .catch(err => console.error("Failed to load fragment", err));
</script>

使用時機:

  • 快速建立原型或概念證明頁面
  • 您同時控制主機頁面和片段樣式的相同來源內容
  • 當最大版面彈性比樣式封裝更重要時
CAUTION
CSS衝突風險
片段的內嵌樣式(包括其<style>區塊、字型宣告和元素選取器)會合併至主機頁面的重疊顯示。
這可能會導致兩個方向都發生意外的樣式覆寫。
只有在您可以容忍或主動管理這些衝突時,才使用此技巧。

iframe iframe

直接將發佈URL載入為<iframe>src。 不需要JavaScript。

iframe內嵌範例:

<iframe
  src="<publish-url>"
  title="Content Fragment Preview"
  width="100%"
  height="600"
  frameborder="0"
  style="border: none;"
></iframe>

您也可以自動調整iframe的大小(這是選擇性的)。

若要將iframe動態調整到其內容高度(避免卷軸),請使用postMessage圖樣或適當的資料庫。

輕量型方法的範例是:

<iframe id="cf-iframe" src="<publish-url>" title="Content Fragment Preview"
  width="100%" frameborder="0" style="border:none; overflow:hidden;"
  onload="this.style.height = this.contentDocument.documentElement.scrollHeight + 'px';"
></iframe>
WARNING
上述onload自動調整大小方法只適用於​相同來源 iframe。
針對​ 跨來源 ​發佈URL,您需要以postMessage為基礎的解決方案或設定固定高度。

使用時機:

  • Edge Delivery Services內嵌區塊(預設整合 — 請參閱下節)
  • 完整CSS/JS隔離很重要的內容
  • 未設定CORS的跨原始內嵌
  • 快速零程式碼整合(只要貼上URL即可)

定義可重複使用的<cf-visualization>自訂元素,它會擷取發佈URL並將HTML插入封裝的影子DOM根中。

此元素提供:

  • 陰影DOM隔離
    • 片段的標籤和樣式會封裝在陰影根中,以免與主機頁面的CSS重疊顯示發生衝突。
  • 內嵌版面配置參與率
    • 演算後的內容會參與主機檔案的正常流程,無需手動維度管理即可回應容器大小調整和Flexbox/Grid內容。
  • 單一瀏覽內容
    • 不會建立次要檔案內容;片段內容會共用頁面的JavaScript執行階段,並可由輔助技術完全週遊。
  • 最低的額外負荷
    • 單一fetch呼叫會從發佈層級擷取預先轉譯的HTML。 不需要使用者端轉譯架構。
IMPORTANT
這是建議用於生產的方法,也是AEM核心元件使用的技術。

若要定義自訂元素,請在每頁加入下列指令碼一次。 頁面上的所有<cf-visualization>執行個體都將使用此定義:

<script>
  class CfVisualization extends HTMLElement {
    connectedCallback() {
      const src = this.getAttribute("src");
      if (!src) return;

      const shadow = this.attachShadow({ mode: "open" });

      fetch(src)
        .then((r) => (r.ok ? r.text() : Promise.reject(r.status)))
        .then((html) => {
          shadow.innerHTML = html;
        })
        .catch((err) => {
          console.error("cf-visualization: failed to load", src, err);
        });
    }
  }

  if (!customElements.get("cf-visualization")) {
    customElements.define("cf-visualization", CfVisualization);
  }
</script>

使用自訂元素:

<cf-visualization src="<publish-url>"></cf-visualization>

使用時機:

  • 使用核心元件的AEM Sites頁面(此為內建行為)
  • 需要乾淨且可重複使用整合的外部/第三方網站
  • 任何需要樣式隔離和配置流程參與的前後關聯

與Edge Delivery Services (內嵌區塊)整合 integration-with-edge-services-embed-block

在Edge Delivery Services中,發佈URL是透過​ 內嵌區塊 ​使用,這會將其呈現為<iframe>

  1. 確認您的專案中存在內嵌區塊。

    如果您的EDS專案尚未包含內嵌區塊,請從aem-block-collection存放庫複製:

    code language-cmdline
    # From the aem-block-collection repo, copy blocks/embed/ into your project's blocks/ directory
    cp -r aem-block-collection/blocks/embed/ your-eds-project/blocks/embed/
    
  2. 在檔案編寫編輯器中編寫內嵌(在Edge Delivery Services中)

    在檔案製作中,區塊會以表格形式呈現。 若要新增內嵌的視覺化內容片段:

    table 0-row-1 1-row-1
    內嵌
    (貼上發佈URL作為超連結)

    或者,如果您的專案或Sidekick在其區塊資料庫中設定了內嵌區塊,您可以透過斜線選單插入該區塊,並將發佈URL貼到區塊內容中。

  3. 結果

    內嵌區塊會在<iframe>內轉譯發佈URL。 片段內容會在EDS頁面版面配置中以完整CSS隔離方式載入。

整合 — AEM Sites與核心元件 integration-aem-sites-with-core-components

內容片段核心元件(core/wcm/components/contentfragment/v1/contentfragment)已內建支援,可使用Customer Element + Shadow DOM技術呈現視覺內容片段。

運作方式:

  • 作者模式:

    當元件的displayMode設定為vcf時,編寫clientlib (vcfRenderer.js)會從預覽API擷取片段HTML,並將其內嵌在編寫畫布中。

    例如,「作者」預覽端點為:

    code language-html
    GET /adobe/sites/cf/fragments/{fragmentId}/preview?templateId={templateId}&variation={variation}
    
  • 發佈模式:

    在已發佈的頁面(wcmmode.disabled)上,HTL範本會轉譯內嵌指令碼,該指令碼會從發佈URL擷取並將HTML插入影子DOM根中。

    核心元件視覺內容片段範例(templates.html):

    code language-html
    <div class="cmp-contentfragment cmp-contentfragment--vcf"
       data-cmp-contentfragment-id="{fragmentId}"
       data-cmp-contentfragment-vcf-template="{templateId}"
       data-cmp-contentfragment-variation="{variation}">
      <!-- Only rendered when wcmmode.disabled (publish) -->
      <div data-vcf-url="{vcfPublishUrl}" class="cmp-contentfragment__vcf-loader" style="display:none"></div>
      <script>
          (function() {
              var script = document.currentScript;
              var loader = script.previousElementSibling;
              var el = script.parentElement;
              if (!el || !loader) return;
              var url = loader.dataset.vcfUrl;
              if (!url) return;
              loader.remove();
              var shadow = el.attachShadow({ mode: "open" });
              var body = document.createElement("body");
              body.style.display = "none";
              shadow.appendChild(body);
              fetch(url)
                  .then(function(r) { return r.ok ? r.text() : Promise.reject(r.status); })
                  .then(function(html) {
                      body.innerHTML = html;
                      body.style.display = "";
                  });
          })();
      </script>
    </div>
    

    發佈URL格式:

    Sling模型(ContentFragmentImpl)會使用下列模式來建置發佈URL:

    code language-html
    /adobe/experimental/previewtemplates-expires-20260301/contentFragments/{templateId}/{fragmentId}/{variation}.html
    

    此相對URL在執行階段會針對發佈主機進行解析。

與外部網站整合 integration-with-external-sites

對於非AEM網站,請使用Customer Element + Shadow DOM技術。 這可提供簡潔的宣告式整合,無需框架相依性。

範例為:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Product Page</title>
</head>
<body>
  <h1>Product Details</h1>
  <p>Some host-page content here...</p>

  <!-- Embed the Content Fragment visualization -->
  <cf-visualization
    src="https://publish-p12345-e67890.adobeaemcloud.com/adobe/experimental/previewtemplates-expires-20260301/contentFragments/product_template/abc-123/master.html"
  ></cf-visualization>

  <p>More host-page content below the fragment...</p>

  <!-- Custom Element definition (include once) -->
  <script>
    class CfVisualization extends HTMLElement {
      connectedCallback() {
        const src = this.getAttribute("src");
        if (!src) return;
        const shadow = this.attachShadow({ mode: "open" });
        fetch(src)
          .then(r => r.ok ? r.text() : Promise.reject(r.status))
          .then(html => { shadow.innerHTML = html; })
          .catch(err => console.error("cf-visualization: failed to load", src, err));
      }
    }
    if (!customElements.get("cf-visualization")) {
      customElements.define("cf-visualization", CfVisualization);
    }
  </script>
</body>
</html>
NOTE
您可以將多個<cf-visualization>元素放置在不同的src個URL的相同頁面上。 自訂元素定義只需包含一次。

CORS和安全性考量事項 cors-and-security-considerations

關注
詳細資料
CORS
內容片段視覺效果服務會以可設定的允許來源設定/adobe/**路徑上的CORS。
內嵌元素(擷取+ innerHTML)🔗 1和客戶元素+ Shadow DOM技術(使用fetch())要求主機頁面的來源必須位於允許清單中。
iFrame技術不需要CORS。
CSP/X-Frame-Options
服務未在發佈的HTML上設定Content-Security-PolicyX-Frame-Options標頭。 如果您的CDN或Dispatcher新增這些標頭,請確認它們允許從您的主機來源建立框架(針對iFrame)或fetch()存取(針對內嵌/陰影DOM)。
內容信任
已發行的HTML會使用由服務管理的Handlebars範本,從已編寫的內容片段資料預先轉譯。 其中不包含使用者產生的指令碼。 不過,和任何innerHTML插入一樣,請確定您信任來源來源。

選擇適當的技術 choose-the-appropriate-technique

使用下列專案作為決定指南,協助您選擇適當的技術:

情境
解決方案
需要零JavaScript和完全隔離嗎?
Iframe
需要樣式隔離的版面配置流程參與嗎?
自訂元素+陰影DOM (建議)
是否可接受最快的原型、相同來源和CSS衝突?
內嵌元素
是否內嵌於Edge Delivery Services?
內嵌區塊(外殼下的iframe)
是否內嵌於AEM Sites頁面?
核心元件(陰影DOM,內建)
recommendation-more-help
experience-manager-cloud-service-help-main-toc