Что есть в Clientlib?

Я веб-дизайнер и разработчик с 2003 года. Я что-то видел и Я что-то писал. Но область Интернета, которую я всегда находил наиболее увлекательной и интересной, - это Front-End. Будь то обсуждение архитектуры / соглашения CSS, поиск новых интересных приемов с помощью Service Workers или игра с Houdini, Front-End - это бесконечная проблема, в которой мы балансируем приоритеты, такие как дизайн / ux, поддержка браузера, доступность и SEO.

Как и многие поставщики Интернета, я получил большую пользу от онлайн-блогов и форумов вопросов и ответов, таких как Stack Overflow. Я почерпнул ценные советы и рекомендации о том, как расширить возможности веб-технологий до их пределов для достижения целей клиентов. Однако в 2018 году я выбрал платформу и проект, не похожий ни на один из предыдущих: запустить сайт на базе проприетарной системы управления контентом от Adobe под названием «Adobe Experience Manager» или в просторечии «AEM».

Что же отличает AEM от других платформ, таких как Drupal / WordPress, Spring или Apollo?

Про Front-End и AEM никто не пишет…

Итак, мы здесь. Цель этой серии статей - описать мой опыт работы в AEM, чтобы предоставить моим коллегам-разработчикам современные инструменты и рабочие процессы Front-End. Приложив немного изобретательности, разработчики AEM могут получить такие тонкости, как PostCSS, Webpack / Rollup и даже Hot Module Replacement (HMR).

Мне нужно многое осветить, поэтому я разбил эту статью на части. Если вы уже знакомы с клиентскими библиотеками AEM, пропустите оставшуюся часть этой статьи и переходите к Части II.

* примечание * - эта серия статей написана с учетом AEM 6.4, но концепции должны применяться к будущим версиям и даже к некоторым более старым (6.2) версиям сенсорного интерфейса.

* примечание * - Adobe печально известна тем, что перемещает свою документацию, а их справочная документация и форумы часто содержат неработающие ссылки. Иногда я добавляю ссылки на их документы, поэтому, если ссылки перестают работать, дайте мне знать, и я постараюсь обновить статью.

Клиентская библиотека (Clientlib)

AEM отправляет клиентские ресурсы конечным пользователям через клиентские библиотеки или клиентские библиотеки. Он составляет эти клиентские библиотеки через .content.xml файл; а затем, необязательно, css.txt файл, js.txtfile и от нуля до множества исходных файлов _4 _ / _ 5_ и .js, которые перечислены в соответствующих файлах .txt. Я расскажу об этих файлах более подробно позже в этой статье.

* примечание * - хотя файлы css.txt и js.txt не требуются, их исключение из clientlib может привести к странным побочным эффектам. Например, если Clientlib A зависит от Clientlib B, но не имеет файла js.txt или css.txt, JS и CSS Clientlib B НЕ будут включены, когда Clientlib A загружается на страницу. Однако, если Clientlib B зависит от Clientlib C, а Clientlib B действительно имеет файлы js.txt и css.txt, тогда JS и CSS Clientlib C в этой ситуации загрузятся нормально. Все это означает, что лучше включать эти файлы .txt, даже если они пустые, чтобы избежать подобных ситуаций.

Эти файлы хранятся в JCR или Java Content Repository, и обновление файлов в JCR обычно приводит к обновлению clientlib (в зависимости от ваших настроек кеширования). Для файлов .less AEM обрабатывает их с помощью компилятора LESS через Rhino. Точная версия Rhino и LESS зависит от вашей версии AEM и пакета обновления.

Затем AEM пытается минимизировать и скрыть (JS) ваши файлы перед объединением их в связанные с ними клиентские библиотеки. По умолчанию это делается с помощью YUI. Его также можно настроить на Google Closure Compiler или none, который просто объединяет файлы.

* совет * - Не используйте YUI для каких-либо клиентских библиотек. YUI - это в значительной степени устаревший инструмент, который может использовать неизвестные селекторы / правила CSS и может взорвать правила ES5, которые идеально подходят для ваших целевых браузеров. Я рекомендую использовать Google Closure Compiler для зависимостей основных компонентов AEM и вариант «none» для любых зависимостей, обрабатываемых Webpack или Rollup. Вместо этого позвольте вашему сборщику обрабатывать такие ситуации.

Файл clientlib .content.xml.

.content.xml файл clientlib похож на проект clientlib. Давайте разберемся:

Пространства имен XML: xmlns: cq и xmlns: jcr
xmlns: cq и Атрибуты xmlns: jcr - это пространства имен XML, используемые для идентификации свойств и значений jcr и cq, используемых в остальной части документа. Их часто можно увидеть перечисленными выше остальных, поскольку они часто устанавливаются, а затем забываются. Оба указанных выше пространства имен необходимы для установки jcr:primaryType текущей папки.

jcr: primaryType строка
Для клиентских библиотек это должно быть cq:ClientLibraryFolder. Это регистрирует родительскую папку для AEM как клиентскую библиотеку.

категории string ‹array›
Массив категорий, к которым принадлежит эта clientlib. Как правило, clientlib будет иметь только одну категорию, и вы почти можете думать об этом как об имени, на которое позже будет ссылаться эта clientlib. Однако могут быть предоставлены и дополнительные категории.

Обычная предопределенная категория, в которую вы можете видеть добавленные библиотеки clientlib, - это cq.authoring.dialog. Это специальная категория, которая загружается для всех диалогов создания в редакторе Touch UI, о котором я расскажу позже. Вы можете увидеть все категории, доступные для вашего экземпляра AEM, посетив страницу dumplibs (http: // localhost: 4502 / libs / granite / ui / content / dumplibs.html) во время работы вашего экземпляра AEM. Вам может потребоваться изменить ваш хост / порт в зависимости от вашей конфигурации.

* совет * - Для загрузки клиентских библиотек в редактор я счел полезным иметь одну клиентскую библиотеку, выделенную для категории cq.authoring.dialog, а затем указать все клиентские библиотеки, которые я хочу загрузить туда, в массиве зависимостей. Эта clientlib должна содержать только файл .content.xml и пустые _21 _ / _ 22_ файлы. Это не позволяет AEM объединить все мои клиентские библиотеки в один большой пакет для редактора и позволяет мне настраивать таргетинг на отдельные клиентские библиотеки с помощью горячей замены модулей.

зависимости string ‹array›
Это массив категорий, на которые опирается эта clientlib. Например, если вы полагаетесь на отдельный комплект зависимостей / поставщика, вы должны указать его здесь. Это поле помогает AEM определить порядок загрузки всех клиентских библиотек, поэтому убедитесь, что вы постоянно обновляете свои зависимости.

встроить (не показано на рисунке выше) string ‹array›
Аналогично зависимостям, встроить используется для указания категорий clientlib, на которые опирается эта clientlib. Однако, в отличие от зависимостей, встраивание фактически объединяет эти клиентские библиотеки вместе. Вообще говоря, вы почти всегда должны предпочесть зависимости, а не встроить. Несоблюдение этого может привести к дублированию кода в клиентских библиотеках или чрезмерному раздутию клиентских библиотек. Однако встраиваемый код полезен для обеспечения доступа к библиотекам, которые хранятся в защищенных областях JCR. Думайте о встраивании как о npm require или import. Поскольку вы, вероятно, используете какую-то настройку сборки Front-End, просто обработайте там свое встраивание.

cssProcessor и jsProcessor string ‹array›
На сайте helpx есть отличная статья о технические подробности здесь, но я хочу остановиться на основных пунктах. По сути, эти два свойства состоят из массива двух значений. Первый указывает, какую обработку вы хотите выполнять по умолчанию или не в производстве. Во-вторых, что он должен делать, когда clientlib нужно минимизировать.

В общем, рассмотрите возможность установки всего на ["default:none", "min:none"] для ваших авторских клиентских библиотек, а затем установите значения по умолчанию cssProcessor: ["default:none", "min:none"] и jsProcessor: ["default:none", "min:gcc;compilationLevel=advanced"] в диспетчере конфигурации. Таким образом, мы можем обрабатывать минимизацию и обфускацию с помощью чего-то вроде Webpack для нашего кода, а клиентские библиотеки Adobe могут обрабатываться через конфигурацию по умолчанию.

* совет * - Мы всегда должны минимизировать и скрывать (если возможно) наш код для производства, но где мы это делаем, зависит от цели clientlib. По умолчанию вам, вероятно, всегда следует указывать none. Это упрощает отладку кода во время разработки. Для минификации ответ немного более тонкий:

Если в вашей clientlib есть встраивание - включите Google Closure Compiler для JS с максимально возможной обфускацией. Для CSS не используйте YUI ни для чего. Повторюсь, YUI печально известен тем, что незаметно поедает селекторы и правила CSS.

Если в вашей clientlib нет встраивания - подумайте о том, чтобы отключить все как для CSS, так и для JS. Вместо этого используйте Webpack, Rollup или любой другой процесс сборки, который обрабатывает минификацию и обфускацию за вас. Вы сможете добиться лучших результатов, используя что-то, адаптированное под ваш код.

allowProxy логическое
Если клиентская библиотека находится в папке / apps (все в папке / apps защищен), это свойство разрешает доступ к нему через прокси-сервлет. Вы можете прочитать больше здесь, но суть в том, что это свойство должно быть установлено, если ваша clientlib находится в / apps, и оно должно находиться в / apps, потому что это имеет больше смысла. организационно. Также существует большая вероятность того, что клиентские библиотеки не будут работать в / etc, продвигаясь вперед, поскольку Adobe переносит все больше и больше кода из / etc.

каналы (не изображены выше) string ‹array›
Это свойство очень полезно, если ваша команда использует функцию экранов в AEM. Это позволяет охватить папку клиентской библиотеки одним или несколькими экранами, что очень удобно, когда библиотеки одной категории предназначены для разных возможностей устройств.

заменяет (не изображено выше) string
Это свойство чаще всего используется при переносе клиентских библиотек в JCR, но может использоваться для замены других существующих библиотек чем-то другим. Значение - это расположение в пути JCR к старой clientlib. Категории также должны соответствовать старой clientlib, чтобы это свойство вступило в силу.

longCacheKey строка
Это свойство плохо документировано, но может быть очень полезным. Это необязательная строка, позволяющая отпечатать ваши клиентские библиотеки (например, clientlib.FINGERPRINT.js). Он даже поддерживает заполнители в значении (например, ${project.version}-${buildNumber}). Это требует настройки build-helper-maven-plugin (см. Примеры).

* Подсказка * - Отпечатки ваших clientlibs - необходимость. Альтернативой longCacheKey для снятия отпечатков является Versioned Clientlibs от ACS AEM Commons. Преимущество этого решения заключается в том, что оно будет хэшировать ваш JS-файл и файлы CSS независимо, даже как часть одной и той же клиентской библиотеки, в отличие от longCacheKey. Однако он требует дополнительной зависимости, поддерживает только хеши MD5 на момент написания этой статьи и требует настройки, чтобы помочь AEM определить хеш. longCacheKey, в конечном счете, более гибкий, но потребует, чтобы у вас были отдельные клиентские библиотеки для JS / CSS, если вы хотите предоставить им отдельные значения.

Папка ресурсов

Ваши библиотеки clientlib могут иметь внешние зависимости. Например, файл CSS может зависеть от файла WOFF для пользовательского шрифта или файла SVG для фонового изображения. Точно так же файл JS может иметь асинхронную зависимость JavaScript, которая загружается в определенном месте области просмотра. В AEM они считаются «ресурсами» и принадлежат подкаталогу resources в каталоге clientlib.

Итак, если ваша clientlib существует здесь, в JCR: / apps / myproject / clientlibs / main
, тогда ваш ресурс будет существовать здесь, в JCR: / apps / myproject / clientlibs / main /resources/font.woff

Затем вы можете получить доступ к этому шрифту, например, в файле css вашей clientlib:

@font-face {
  font-family: "Open Sans";
  src: url("resources/font.woff") format("woff");
}

Вы также можете вложить дополнительные каталоги в ресурсы в зависимости от потребностей вашей организации, чтобы указанный выше URL-адрес шрифта мог быть resources / fonts / font.woff.

* совет * - вы можете поместить любой статический файл в папку ресурсов, он не должен быть только активом, на который может ссылаться clientlib. Например, иногда у меня есть большие внешние SVG (например, спрайты), которые я не хочу хранить в DAM, потому что я полагаюсь на них в своих компонентах. Хранение их в папке ресурсов clientlib дает мне согласованную точку отсчета, которую я могу использовать где угодно.

Компонентно-зависимые клиентские библиотеки

В мире HTTP / 2 все чаще возникает соблазн создавать отдельные клиентские библиотеки для каждого компонента и доставлять их по мере необходимости. Это может иметь большой смысл, особенно при работе с несколькими сайтами, совместно использующими компоненты в одном экземпляре AEM. В настоящее время AEM не поддерживает HTTP / 2 для всех запросов, но его можно настроить на использование HTTP / 2 для доставки контента.

К сожалению, загрузка зависимых от компонентов клиентских библиотек - это совсем другая история. В настоящее время нет возможности сделать это из коробки. Как говорится в статье на форуме, существуют индивидуальные решения, которые потенциально могут решить эту проблему, но сопряжены с риском. Однако следует подчеркнуть, что это относится к CSS и JavaScript в <head>. Если вам нужно загрузить JavaScript для конкретного компонента в конце <body>, вы, вероятно, сможете разместить вызовы clientlib внутри HTL компонентов.

Наконец, ничто из вышеперечисленного не применимо к модулям JavaScript AMD (определение асинхронного модуля) или асинхронно загружаемым CSS. Они могут существовать как ресурсы в основной папке clientlib и могут быть извлечены так же, как и в любом другом проекте.

extraClientLibs
Практически полностью изменив то, что было только что написано, вы МОЖЕТЕ иметь специфичный для компонента JavaScript и CSS для диалогового окна Touch UI вашего компонента. Это можно сделать с помощью свойства extraClientLibs .content.xml файла компонента. Эта функция, заблокированная для редактора, действительно прискорбна, но она может быть полезна, если вы разрабатываете тяжелые диалоговые компоненты.

Заключение

Для начинающего Front-End разработчика AEM нужно немного привыкнуть к Clientlib. Это не так просто, как сбросить статические ресурсы в корзину и указать на них теги <script> и <style>. Но теперь, когда мы знаем все плюсы и минусы работы с clientlib, мы можем опираться на этот фундамент для создания действительно вдохновляющих и доступных интерфейсов.

Далее: Часть II: День СПА