现代网站严重依赖由复杂的JavaScript和CSS代码驱动的客户端处理。 组织和优化此代码的服务可能是一个复杂的问题。
为帮助解决此问题,AEM提供客户端库文件夹,允许您将客户端代码存储在存储库中,将其组织到类别中,并定义何时以及如何将每个类别代码提供给客户端。 然后,客户端库系统负责在最终网页中生成正确的链接以加载正确的代码。
在页面的HTML中包含客户端库(即JS或CSS文件)的标准方法是,在该页面的JSP中包含<script>
或<link>
标记,其中包含该文件的路径。 例如,
...
<head>
...
<script type="text/javascript" src="/etc/clientlibs/granite/jquery/source/1.8.1/jquery-1.8.1.js"></script>
...
</head>
...
虽然此方法在AEM中有效,但在页面及其组成组件变得复杂时,可能会导致问题。 在这种情况下,同一JS库的多个副本可能会包含在最终HTML输出中。 要避免这种情况并允许客户端库的逻辑组织,AEM使用客户端库文件夹。
客户端库文件夹是类型cq:ClientLibraryFolder
的存储库节点。 它在CND记号中的定义是
[cq:ClientLibraryFolder] > sling:Folder
- dependencies (string) multiple
- categories (string) multiple
- embed (string) multiple
- channels (string) multiple
默认情况下,cq:ClientLibraryFolder
节点可以放置在存储库的/apps
、/libs
和/etc
子树中的任意位置(这些默认值以及其他设置可以通过系统控制台的Adobe花岗岩HTML库管理器面板进行控制)。
每个cq:ClientLibraryFolder
都会填入一组JS和/或CSS文件,以及一些支持文件(见下文)。 cq:ClientLibraryFolder
的属性配置如下:
categories
:标识今秋JS和/或CSS文件集所属的 cq:ClientLibraryFolder
类别。categories
属性具有多值,允许库文件夹属于多个类别的一部分(请参见下面,了解这有何用)。
dependencies
:这是此库文件夹所依赖的其他客户端库类别的列表。例如,给定两个cq:ClientLibraryFolder
节点F
和G
,如果F
中的文件需要G
中的另一个文件才能正常工作,则G
的categories
中的至少一个应位于F
的dependencies
中。
embed
:用于嵌入来自其他库的代码。如果节点F嵌入节点G和H,则生成的HTML将是节点G和H中的内容集中。
allowProxy
:如果客户端库位于下 /apps
方,则此属性允许通过代理servlet访问它。请参阅下面的查找客户端库文件夹和使用代理客户端库Servlet。
由于HTL是开发AEM站点的首选技术,因此应使用HTL在AEM中包含客户端库。 但是,也可以使用JSP进行此操作。
在HTL中,客户端库通过AEM提供的帮助模板加载,可通过 data-sly-use
访问该模板。 此文件中有三个模板,可通过 data-sly-call
调用它们:
每个帮助程序模板都需要一个categories
选项来引用所需的客户端库。 该选项可以是字符串值的数组,也可以是包含逗号分隔值列表的字符串。
有关更多详细信息和用法示例,请参阅文档HTML模板语言入门。
向JSP代码中添加ui:includeClientLib
标记,以在生成的HTML页面中添加指向客户端库的链接。 要引用库,请使用ui:includeClientLib
节点的categories
属性的值。
<%@taglib prefix="ui" uri="https://www.adobe.com/taglibs/granite/ui/1.0" %>
<ui:includeClientLib categories="<%= categories %>" />
例如,/etc/clientlibs/foundation/jquery
节点的类型为cq:ClientLibraryFolder
,其类别属性为cq.jquery
。 JSP文件中的以下代码引用库:
<ui:includeClientLib categories="cq.jquery"/>
生成的HTML页包含以下代码:
<script type="text/javascript" src="/etc/clientlibs/foundation/jquery.js"></script>
有关包括筛选JS、CSS或主题库的属性在内的完整信息,请参阅ui:includeClientLib。
<cq:includeClientLib>
过去常用于包含客户端库,自AEM 5.6起已弃用它。应 <ui:includeClientLib>
如上所述使用它。
创建一个cq:ClientLibraryFolder
节点以定义JavaScript和层叠样式表库,并使它们可用于HTML页面。 使用节点的categories
属性标识它所属的库类别。
该节点包含一个或多个在运行时合并为单个JS和/或CSS文件的源文件。 生成的文件的名称是扩展名为.js
或.css
的节点名称。 例如,名为cq.jquery
的库节点生成名为cq.jquery.js
或cq.jquery.css
的生成文件。
客户端库文件夹包含以下项目:
要合并的JS和/或CSS源文件。
支持CSS样式的资源,如图像文件。
注意: 您可以使用子文件夹来组织源文件。
一个js.txt
文件和/或一个css.txt
文件,用于标识要合并到生成的JS和/或CSS文件中的源文件。
有关构件的客户端库特定要求的信息,请参阅使用和扩展构件。
Web客户端必须具有访问cq:ClientLibraryFolder
节点的权限。 您还可以从存储库的安全区域中显示库(请参阅下面的“从其他库嵌入代码”)。
位于/apps
下的客户端库文件夹优先于位于/libs
中的同名文件夹。 例如,/apps/cq/ui/widgets
优先于/libs/cq/ui/widgets
。 当这些库属于同一类别时,将使用/apps
下的库。
在以前的版本中,客户端库文件夹位于存储库中/etc/clientlibs
的下方。 这仍受支持,但建议现在在/apps
下放置客户端库。 这是在其他脚本附近找到客户端库,通常位于/apps
和/libs
下。
客户端库文件夹下的静态资源必须位于名为resources的文件夹中。 如果文件夹resources下没有静态资源(如图像),则无法在发布实例上引用它。 以下是一个示例:https://localhost:4503/etc.clientlibs/geometrixx/components/clientlibs/resources/example.gif
为了更好地从内容和配置中隔离代码,建议在/apps
下找到客户端库,并通过/etc.clientlibs
利用allowProxy
属性来公开它们。
为了使/apps
下的客户端库可访问,使用代理服务器。 ACL仍然强制在客户端库文件夹上,但如果allowProxy
属性设置为true
,则servlet允许通过/etc.clientlibs/
读取内容。
静态资源只能通过代理访问,如果它位于客户端库文件夹下的资源下。
例如:
/apps/myproject/clientlibs/foo
中有一个clientlib/apps/myprojects/clientlibs/foo/resources/icon.png
中有静态图像然后,将foo
上的allowProxy
属性设置为true。
/etc.clientlibs/myprojects/clientlibs/foo.js
/etc.clientlibs/myprojects/clientlibs/foo/resources/icon.png
引用图像使用代理客户端库时,AEM Dispatcher配置可能需要更新以确保允许具有扩展客户端库的URI。
Adobe建议在/apps
下找到客户端库,并使用代理servlet使其可用。 但是,请记住,最佳做法仍然要求公共站点不要包含直接通过/apps
或/libs
路径提供服务的任何内容。
在Web浏览器中打开CRXDE Lite(https://localhost:4502/crx/de)。
选择要查找客户端库文件夹的文件夹,然后单击创建>创建节点。
输入库文件的名称,在“类型”列表中选择cq:ClientLibraryFolder
。 单击确定,然后单击保存全部。
要指定库所属的类别或类别,请选择cq:ClientLibraryFolder
节点,添加以下属性,然后单击全部保存:
通过任何方式将源文件添加到库文件夹。 例如,使用WebDav客户端复制文件,或创建文件并手动创作内容。
注意:如 果需要,可以在子文件夹中组织源文件。
选择客户端库文件夹,然后单击创建>创建文件。
在“文件名”框中,键入以下文件名之一,然后单击“确定”:
js.txt
: 使用此文件名生成JavaScript文件。css.txt
: 使用此文件名生成层叠样式表。打开文件并键入以下文本以标识源文件路径的根:
#base=*[root]*
将* [root]
*替换为包含源文件的文件夹(相对于TXT文件)的路径。 例如,当源文件与TXT文件位于同一文件夹中时,请使用以下文本:
#base=.
以下代码将根设置为cq:ClientLibraryFolder
节点下名为mobile的文件夹:
#base=mobile
在#base=[root]
下面的行中,键入源文件相对于根的路径。 将每个文件名放在单独的行上。
单击保存全部。
当客户端库文件夹中的代码引用其他库时,将其他库标识为依赖关系。 在JSP中,引用客户端库文件夹的ui:includeClientLib
标记会导致HTML代码包含指向生成的库文件以及依赖项的链接。
依赖关系必须是另一个cq:ClientLibraryFolder
。 要标识依赖关系,请向cq:ClientLibraryFolder
节点添加一个属性,其中包含以下属性:
例如,/ etc/clientlibs/myclientlibs/publicmain
对cq.jquery
库具有依赖关系。 引用主客户端库的JSP生成包含以下代码的HTML:
<script src="/etc/clientlibs/foundation/cq.jquery.js" type="text/javascript">
<script src="/etc/clientlibs/mylibs/publicmain.js" type="text/javascript">
可以将客户端库中的代码嵌入到另一个客户端库中。 在运行时,嵌入库生成的JS和CSS文件包括嵌入库的代码。
嵌入代码对于提供对存储在存储库的安全区域中的库的访问非常有用。
最好将所有与应用程序相关的文件保留在/app
下的其应用程序文件夹中。 拒绝网站访客访问/app
文件夹也是最佳做法。 为了同时满足这两种最佳实践,请在/etc
文件夹下创建一个客户端库文件夹,它嵌入位于/app
下的客户端库。
使用类别属性标识要嵌入的客户端库文件夹。 要嵌入库,请使用以下属性属性向嵌入cq:ClientLibraryFolder
节点添加属性:
cq:ClientLibraryFolder
性的值。在某些情况下,您可能会发现,发布实例为典型页面生成的最终HTML包含相对大量的<script>
元素,尤其是当站点使用Client Context信息进行分析或定位时。 例如,在未优化的项目中,您可能会在页面的HTML中找到以下系列<script>
元素:
<script type="text/javascript" src="/etc/clientlibs/granite/jquery.js"></script>
<script type="text/javascript" src="/etc/clientlibs/granite/utils.js"></script>
<script type="text/javascript" src="/etc/clientlibs/granite/jquery/granite.js"></script>
<script type="text/javascript" src="/etc/clientlibs/foundation/jquery.js"></script>
<script type="text/javascript" src="/etc/clientlibs/foundation/shared.js"></script>
<script type="text/javascript" src="/etc/clientlibs/foundation/personalization/kernel.js"></script>
在这种情况下,将所有所需的客户端库代码合并到单个文件中,以减少页面加载时来回请求的数量,这是非常有用的。 为此,您可以使用cq:ClientLibraryFolder
节点的embed属性,将所需的库embed
导入应用程序特定的客户端库。
以下客户端库类别包含在AEM中。 您应仅嵌入特定站点运行所需的内容。 但是,您应保持此处列出的顺序:
browsermap.standard
browsermap
jquery-ui
cq.jquery.ui
personalization
personalization.core
personalization.core.kernel
personalization.clientcontext.kernel
personalization.stores.kernel
personalization.kernel
personalization.clientcontext
personalization.stores
cq.collab.comments
cq.collab.feedlink
cq.collab.ratings
cq.collab.toggle
cq.collab.forum
cq.cleditor
嵌入CSS文件时,生成的CSS代码使用相对于嵌入库的资源的路径。 例如,可公开访问的库/etc/client/libraries/myclientlibs/publicmain
嵌入了/apps/myapp/clientlib
客户端库:
main.css
文件包含以下样式:
body {
padding: 0;
margin: 0;
background: url(images/bg-full.jpg) no-repeat center top;
width: 100%;
}
publicmain
节点生成的CSS文件包含以下样式,使用原始图像的URL:
body {
padding: 0;
margin: 0;
background: url(../../../apps/myapp/clientlib/styles/images/bg-full.jpg) no-repeat center top;
width: 100%;
}
使用客户端库文件夹的channels
属性来标识使用该库的移动组。 当为不同的设备功能设计相同类别的库时,channels
属性很有用。
要将客户端库文件夹与设备组关联,请向cq:ClientLibraryFolder
节点添加以下属性:
例如,下表列表了cq.widgets
类别的每个客户端库文件夹的channels
属性的值:
客户端库文件夹 | 渠道属性的值 |
---|---|
/libs/cq/analytics/widgets |
!touch |
/libs/cq/analytics/widgets/themes/default |
!touch |
/libs/cq/cloudserviceconfigs/widgets |
!touch |
/libs/cq/searchpromote/widgets |
!touch |
/libs/cq/searchpromote/widgets/themes/default |
[无值] |
/libs/cq/touch/widgets |
touch |
/libs/cq/touch/widgets/themes/default |
touch |
/libs/cq/ui/widgets |
!touch |
/libs/cq/ui/widgets/themes/default |
!touch |
AEM支持可插拔的预处理器,并附带对YUI Compressor的CSS和JavaScript支持以及Google Closure Compiler(GCC)的JavaScript支持,YU设置为AEM默认预处理器。
可插拔预处理器允许灵活使用,包括:
默认情况下,AEM使用YUI压缩程序。 有关一列表已知问题,请参阅YUI Compressor GitHub文档。 对于特定客户端,切换到GCC压缩程序可解决使用YUI时观察到的一些问题。
不要将精简库放在客户端库中。 而是提供原始库,如果需要进行微型化,请使用预处理器的选项。
您可以选择根据客户端库或系统范围配置预处理器配置。
在clientlibrary节点上添加多值属性cssProcessor
和jsProcessor
或通过HTML库管理器 OSGi配置定义系统默认配置
clientlib节点上的预处理器配置优先于OSGI配置。
config:= mode ":" processorName options*;
mode:= "default" | "min";
processorName := "none" | <name>;
options := ";" option;
option := name "=" value;
cssProcessor: ["default:none", "min:yui"]
jsProcessor: ["default:none", "min:gcc;compilationLevel=advanced"]
jsProcessor: [
"default:typescript",
"min:typescript",
"min:gcc;obfuscate=true"
]
failOnWarning (defaults to "false")
languageIn (defaults to "ECMASCRIPT5")
languageOut (defaults to "ECMASCRIPT5")
compilationLevel (defaults to "simple") (can be "whitespace", "simple", "advanced")
有关GCC选项的更多详细信息,请参阅GCC文档。
在AEM中,YUI设置为默认的minifier。 要将此更改为GCC,请执行以下步骤。
转到位于https://localhost:4502/system/console/configMgr的Apache Felix Config Manager
查找并编辑AdobeGranite HTML库管理器。
启用Minify选项(如果尚未启用)。
将值JS处理器默认配置设置为min:gcc
。
如果以分号分隔,则可以传递选项,例如min:gcc;obfuscate=true
。
单击保存以保存更改。
AEM提供了多种工具用于调试和测试客户端库文件夹。
要跟踪嵌入代码的来源,或确保嵌入的客户端库生成预期结果,您可以在运行时查看嵌入的文件名称。 要查看文件名,请在网页的URL后面附加debugClientLibs=true
参数。 生成的库包含@import
语句,而不是嵌入代码。
在前一个从其他库嵌入代码部分的示例中,/etc/client/libraries/myclientlibs/publicmain
客户端库文件夹嵌入了/apps/myapp/clientlib
客户端库文件夹。 将参数追加到网页后,将在网页的源代码中生成以下链接:
<link rel="stylesheet" href="/etc/clientlibs/mycientlibs/publicmain.css">
打开publicmain.css
文件会显示以下代码:
@import url("/apps/myapp/clientlib/styles/main.css");
在Web浏览器的地址框中,将以下文本追加到HTML的URL:
?debugClientLibs=true
载入页面时,视图页面源。
单击作为链接元素的href提供的链接以打开文件并视图源代码。
/libs/cq/granite/components/dumplibs/dumplibs
组件会生成有关系统上所有客户端库文件夹的信息页面。 /libs/granite/ui/content/dumplibs
节点将组件作为资源类型。 要打开页面,请使用以下URL(根据需要更改主机和端口):
https://<host>:<port>/libs/granite/ui/content/dumplibs.test.html
信息包括库路径和类型(CSS或JS)以及库属性的值,如类别和依赖关系。 页面上的后续表显示了每个类别和渠道中的库。
dumplibs
组件包含一个测试选择器,它显示为ui:includeClientLib
标记生成的源代码。 该页面包含js、css和主题属性的不同组合的代码。
使用以下方法之一打开“测试输出”页:
在dumplibs.html
页面中,单击单击此处以输出测试文本中的链接。
在Web浏览器中打开以下URL(根据需要使用不同的主机和端口):
http://<host>:<port>/libs/granite/ui/content/dumplibs.html
默认页显示没有类别属性值的标记的输出。
要查看类别的输出,请键入客户端库的categories
属性值,然后单击提交查询。
HTML库管理器服务处理cq:ClientLibraryFolder
标记,并在运行时生成库。 环境、开发或生产类型决定了您应如何配置服务:
有关配置服务的信息,请参阅AEM HTML Library Manager。