Что такое библиотека ресурсов JSF и как ее использовать? Зачем нужен валидный код и как устранить ошибки валидации. Асинхронная загрузка CSS

Что такое библиотека ресурсов JSF и как ее использовать? Зачем нужен валидный код и как устранить ошибки валидации. Асинхронная загрузка CSS

16.02.2019

к.э.н. Лавлинский Н. Е., технический директор ООО «Метод Лаб»

Недавно опубликован новый стандарт на технологию Preload (ссылка). Основной задачей этой спецификации было обеспечить возможность тонкого управления логикой загрузки ресурсов страницы разработчиком.

Предыдущие стандарты

Идея об управлении загрузкой не нова. Ранее были разработаны несколько вариантов тегов link с атрибутами subresource , prerender и prefetch . Однако, они работали несколько иначе: с их помощью можно загружать элементы страниц или целые страницы, которые могут потребоваться при дальнейшей навигации по сайту. То есть, браузер отправлял такие запросы с низким приоритетом и в последнюю очередь. Если же нужно повысить приоритет, то решений не было.

Загрузка ресурсов с preload

Что же даёт новая спецификация? Во-первых, теперь загрузка происходит с уточнением, что загружается. Исходя из указанного типа ресурса браузером выставляется приоритет загрузки. Например:

link rel = "preload" href = "/js/script.js" as= "script" >
link rel = "preload" href = "/fonts/1.woff2" as= "font" type = "font/woff2" crossorigin>

Во-вторых, тип ресурса (as ) позволяет браузеру послать правильные заголовки, чтобы сервер мог отправить контент с лучшим вариантом сжатия (например, послать WebP картинки, если браузер их поддерживает).

Во втором примере мы загружаем файл шрифта, при этом указан конкретный формат (WOFF2), который поддерживается не всеми браузерами. Однако, пока поддержка механизма preload совпадает с поддержкой такого формата, проблем не возникает. Текущую поддержку механизма можно посмотреть .

Ускоренная загрузка шрифтов

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

Если мы укажем preload этого шрифта в коде HTML-страницы, браузер отправит запрос сразу же после разбора HTML-документа, что может быть на несколько секунд раньше, чем в обычном случае. А мы знаем, что подключаемые шрифты являются блокирующими элементами и задерживают отрисовку шрифта на странице, поэтому загрузить их нужно как можно быстрее. Особенно остро эта проблема стоит при использовании HTTP/2, когда браузер отправляет сразу множество запросов к серверу, в результате чего какие-нибудь картинки могут заполнить полосу клиента и загрузка важных ресурсов будет отложена.

Асинхронная загрузка CSS

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

Делается это следующим образом:

link rel = "preload" as= "style" href = "async_style.css" onload = "this.rel="stylesheet"" > Загрузка JS-кода без исполнения

Также полезным может оказаться предзагрузка кода скрипта на JS, чтобы выполнить его позже.

Это можно сделать с помощью следующего кода:

link rel = "preload" as= "script" href = "async_script.js" onload = "var script = document.createElement("script"); script.src = this.href; document.body.appendChild(script);" >

Мы рассмотрели основные способы использования механизма preload, но возможности на этом не ограничиваются, проводите собственные эксперименты!

Консорциум Всемирной паутины (World Wide Web Consortium, W3C) рекомендовал технологию CSS (Cascading Style Sheets) в 1996 году. С тех пор веб-разработчики используют каскадные таблицы стилей для создания уникального оформления сайтов.

Двадцать лет назад разработчики играли с параметрами шрифтов, атрибутами текста и цветами элементов страницы. Сейчас в ходу анимации, тени, градиенты, сглаживания и многие другие продвинутые вещи.

Установите расширение Web Developer для Chrome или дополнение Disable CSS для Firefox, чтобы полюбоваться любимыми сайтами без каскадных таблиц стилей.

Изменения будут разительными, хотя и не всегда. Например, новостной агрегатор Drudge Report почти не изменится: он прост как дважды два. Тем не менее ежемесячно ресурс просматривают свыше 150 миллионов раз.

Где научиться тонкостям CSS

Будем последовательны и начнём с крепкой теоретической базы. За ней обратимся к Владу Мержевичу, автору книг и веб-разработчику, который поддерживает несколько качественных ресурсов о вёрстке и стилизации веб-страниц.

На вы найдёте понятный самоучитель и ответы на популярные вопросы о каскадных таблицах стилей. Здесь же представлены обучающие статьи об актуальной третьей спецификации CSS.

Предлагает алфавитный справочник по CSS. Каждое свойство имеет краткое описание, синтаксис и живой пример. Не стесняйтесь задавать вопросы - авторы проекта выходят на связь и охотно обсуждают детали.

В дополнение к русскоязычным самоучителям добавим зарубежные сайты. Некоторым студентам с их помощью проще вникать в профессию и принимать её терминологию. Поэтому всё внимание на . На сайте нет ничего лишнего: свойства CSS, пояснения и действие. Из приятных мелочей отметим быстрый поиск и копирование свойства в буфер обмена по щелчку мыши.

Обучение - дело долгое и порой скучное. Неплохо бы найти мотивацию, чтобы она помогала в трудные минуты. Вдохновляться будем у других веб-дизайнеров, а точнее на сайте . Здесь каждый день представляют качественный проект, который служит образцом того, к чему стоит стремиться. Многие из победителей действительно удивляют. Не забывайте заглядывать и голосовать за понравившихся номинантов.

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

Загрузите эталонный HTML, добавьте своё оформление и отправьте всё это обратно. Возможно, ваш подход окажется самым лучшим. К слову, можно скачать чужой вариант и посмотреть, как же он реализован.

Понятное дело, что вам захочется применить нечто эдакое, что привлечёт всеобщее внимание. Не знаем, есть ли такое на , но десятки и сотни любопытных приёмов там точно завалялись.

Скачать код напрямую не получится. Вам придётся залезть в меню разработчиков - такова политика местной партии. При этом подавляющее большинство CSS-стилей можно использовать без разрешения автора.

Зачем нам чужое, если у самих руки прямо растут? Так ли оно на самом деле покажет . Помимо базовой проверки синтаксиса CSS, веб-сервис выполняет проверку на соответствие правилам, которые влияют на скорость загрузки страниц. На выходе получаем хороший, милый для браузеров CSS-код.

А какие ресурсы о каскадных таблицах стилей можете посоветовать вы?

Имеют атрибут library . Что это и как это следует использовать? В Интернете есть много примеров, которые используют его как общий тип содержимого/файла css , js и img (или image) в качестве имени библиотеки в зависимости от используемого тега:

Как это полезно? Значение library в этих примерах, похоже, просто повторяет то, что уже было представлено именем тега. Для он основан на имени тега, уже очевидном, что он представляет собой "библиотеку CSS". Какая разница со следующим, который также работает так же?

Кроме того, сгенерированный вывод HTML немного отличается. Учитывая путь контекста отображения /contextname и FacesServlet в шаблоне URL-адреса *.xhtml , первый генерирует следующий HTML-код с именем библиотеки в качестве параметра запроса:

Пока последний генерирует следующий HTML-код с именем библиотеки только по пути URI:

Последний подход делает задним числом также более ощутимым, чем прежний подход. Как же полезен атрибут library ?

1 ответ

Фактически, все эти примеры в Интернете, где общий тип содержимого/файла типа "js", "css", "img" и т.д. используется как имя библиотеки вводящий в заблуждение .

Примеры реального мира

Для начала рассмотрим, как существующие реализации JSF, такие как Mojarra и MyFaces и библиотеки компонентов JSF, такие как PrimeFaces и OmniFaces использовать его. Ни один из них не использует библиотеки ресурсов таким образом. Они используют его (под обложками или ) следующим образом:

Понятно, что в основном это имя общей библиотеки/модуля/темы , где все эти ресурсы обычно принадлежат.

Легче идентифицировать

Таким образом, гораздо проще указывать и различать, где эти ресурсы принадлежат и/или происходят. Представьте, что у вас есть ресурс primefaces.css в вашем собственном webapp, в котором вы переопределяете/завершаете некоторые CSS CSS по умолчанию; если PrimeFaces не использует имя библиотеки для своего собственного primefaces.css , тогда собственный PrimeFaces не будет загружен, а вместо него будет поставляться с помощью webapp, что сломает look"n"feel.

Кроме того, когда вы используете пользовательский , вы также можете применять более мелкозернистый контроль над ресурсами, поступающими из определенной библиотеки когда library используется правильно. Если бы все библиотеки компонентов использовали "js" для всех своих JS файлов, как бы ResourceHandler когда-либо отличалось, если бы оно исходило из конкретной библиотеки компонентов? Примерами являются OmniFaces и ; проверьте метод createResource() , в котором библиотека проверена перед передачей следующему обработчику ресурсов в цепочке. Таким образом, они знают, когда создавать CombinedResource или GraphicResource для этой цели.

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

Ваш собственный webapp

Ваш собственный webapp не обязательно нуждается в библиотеке ресурсов. Лучше всего просто опустить это.

Или, если вам действительно нужно иметь его, вы можете просто дать ему более разумное общее имя, например "default" или какое-то название компании.

Или, когда ресурсы специфичны для какого-либо шаблона Masterlets, вы также можете указать ему имя шаблона, чтобы было легче связать друг друга. Другими словами, это больше для самодокументированных целей. Например. в файле шаблона /WEB-INF/templates/layout.xhtml:

И файл шаблона /WEB-INF/templates/admin.xhtml:

Для примера в реальном мире проверьте исходный код витрины OmniFaces .

Или, если вы хотите разделить одни и те же ресурсы по нескольким веб-папкам и создали для них общий проект, основанный на том же примере, что и в этом ответе , который, в свою очередь, встроен в JAR в webapp /WEB-INF/lib , а затем ссылается на него как на библиотеку (имя по своему выбору, так что такие библиотеки компонентов, как OmniFaces и PrimeFaces):

Управление версиями библиотеки

Другим основным преимуществом является то, что вы можете правильно использовать правильную версию библиотеки ресурсов на ресурсах, предоставляемых вашим собственным webapp (это не работает для ресурсов, встроенных в JAR). Вы можете создать прямую дочернюю подпапку в папке библиотеки с именем в шаблоне \d+(_\d+)* , чтобы обозначить версию библиотеки ресурсов.

WebContent |-- resources | `-- default | `-- 1_0 | |-- css | | `-- style.css | |-- img | | `-- logo.png | `-- js | `-- script.js:

При использовании этой разметки:

Это приведет к созданию следующего HTML с версией библиотеки как v:

Итак, если вы отредактировали/обновили какой-то ресурс, все, что вам нужно сделать, это скопировать или переименовать папку версии в новое значение. Если у вас несколько папок с версиями, то JSF ResourceHandler будет автоматически обслуживать ресурс с наивысшего номера версии в соответствии с правилами численного заказа.

Итак, при копировании/переименовании resources/default/1_0/* в папку resources/default/1_1/* , как показано ниже:

WebContent |-- resources | `-- default | |-- 1_0 | | : | | | `-- 1_1 | |-- css | | `-- style.css | |-- img | | `-- logo.png | `-- js | `-- script.js:

Затем в последнем примере разметки будет создан следующий HTML-код:

Это заставит веб-браузер запрашивать ресурс прямо с сервера вместо того, чтобы показывать тот же имя из кеша, когда URL-адрес с измененным параметром был запрошен в первый раз. Таким образом, конечным пользователям не требуется выполнять жесткое обновление (Ctrl + F5 и т.д.), Когда им нужно получить обновленный ресурс CSS/JS.

Последнее обновление: 27.01.2016

В WPF важное место занимают ресурсы . В данном случае под ресурсами подразумеваются не дополнительные файлы (или физические ресурсы ), как, например, аудиофайлы, файлы с изображениями, которые добавляются в проект. Здесь речь идет о логических ресурсах , которые могут представлять различные объекты - элементы управления, кисти, коллекции объектов и т.д. Логические ресурсы можно установить в коде XAML или в коде C# с помощью свойства Resources . Данное свойство опредлено в базовом классе FrameworkElement , поэтому его имеют большинство классов WPF.

В чем смысл использования ресурсов? Они повышают эффективность: мы можем определить один раз какой-либо ресурс и затем многократно использовать его в различных местах приложения. В связи с этим улучшается поддержка - если возникнет необходимость изменить ресурс, достаточно это сделать в одном месте, и изменения произойдут глобально в приложении.

Свойство Resources представляет объект ResourceDictionary или словарь ресурсов, где каждый хранящийся ресурс имеет определенный ключ.

Определение ресурсов

Определим ресурс окна и ресурс кнопки:

Здесь у окна определяются два ресурса: redStyle, который представляет объект SolidColorBrush, и gradientStyle, который представляет кисть с линейным градиентом. У кнопки определен один ресурс darkStyle, представляющий кисть SolidColorBrush. Причем каждый ресурс обязательно имеет свойство x:Key , которое и определяе ключ в словаре.

А в свойствах Background соответственно у грида и кнопки мы можем применить эти ресурсы: Background="{StaticResource gradientStyle}" - здесь после выражения StaticResource идет ключ применяемого ресурса.

Управление ресурсами в коде C#

Добавим в словарь ресурсов окна градиентную кисть и установим ее для кнопки:

// определение объекта-ресурса LinearGradientBrush gradientBrush = new LinearGradientBrush(); gradientBrush.GradientStops.Add(new GradientStop(Colors.LightGray, 0)); gradientBrush.GradientStops.Add(new GradientStop(Colors.White, 1)); // добавление ресурса в словарь ресурсов окна this.Resources.Add("buttonGradientBrush", gradientBrush); // установка ресурса у кнопки button1.Background = (Brush)this.TryFindResource("buttonGradientBrush"); // или так //button1.Background = (Brush)this.Resources["buttonGradientBrush"];

С помощью свойства Add() объект кисти и его произвольный ключ добавляются в словарь. Далее с помощью метода TryFindResource() мы пытаемся найти ресурс в словаре и установить его в качестве фона. Причем, так как этот метод возвращает object, необходимо выполнить приведение типов.

Всего у ResourceDictionary можно выделить следующие методы и свойства:

    Метод Add(string key, object resource) добавляет объект с ключом key в словарь, причем в словарь можно добавить любой объект, главное ему сопоставить ключ

    Метод Remove(string key) удаляет из словаря ресурс с ключом key

    Свойство Uri устанавливает источник словаря

    Свойство Keys возвращает все имеющиеся в словаре ключи

    Свойство Values возвращает все имеющиеся в словаре объекты

Для поиска нужного ресурса в коллекции ресурсов у каждого элемента определены методы FindResource() и TryFindResource() . Она оба возвращают ресурс, соответствующий определенному ключу. Единственное различие между ними состоит в том, что FindResource() генерирует исключение, если ресурс с нужным ключом не был найден. А метод TryFindResource() в этом случае просто возвращает null.

Разделяемые ресурсы

Когда один и тот же ресурс используется в разных местах, то фактически мы используем один и тот же объект. Однако это не всегда желательно. Иногда необходимо, чтобы примение ресурса к разным объектам различалось. То есть нам необходимо, чтобы при каждом применении создавался отдельный объект ресурса. В этом случае мы можем изспользовать выражение x:Shared="False" :

Примеры использования ресурсов

Рассмотрим еще пару примеров применения ресурсов. К примеру, если мы хотим, чтобы ряд кнопок обладал одинаковыми свойствами, то мы можем определить одну общую кнопку в качестве ресурса:

Другой пример - определение списка объектов для списковых элементов:

iPhone 6S Nexus 6P Lumia 950 Xiaomi MI5

В последнее время неоднократно всплывает тема загрузки ресурсов. Вкратце: «Я загружаю картинку из c:\work\image.gif, а когда запускаю программу из jar-файла/на другом компьютере – она не грузится. Что делать?».

Между тем, ничего сложного тут нет. Надо только понимать принципы.

Прежде всего, грузить ресурсы по абсолютному адресу на диске – занятие бесперспективное. Думаю, сами прекрасно понимаете, почему – убрали файл с диска, и «прощай ресурс». Всё свое надо носить с собой.

Второй вариант, который я часто вижу, – загрузка ресурса из jar-файла. Но тут очень часто делается одна ошибка – ресурс пытаются грузить через класс java.io.File . При том, что этот класс предназначен только для работы с файловыми системами.

Хотя сама идея правильная. Нужный ресурс действительно необходимо поместить в jar-файл. Надо только понимать, как его оттуда загрузить. Вот об этом я и расскажу.

Для загрузки ресурса служат методы java.lang.Class.getResource(String) , java.lang.Class.getResourceAsStream(Stri ng) , java.lang.ClassLoader.getResource(String) и java.lang.ClassLoader.getResourceAsStrea m(String) . Методы Class -а делегируют вызовы ClassLoader -у.

GetResource(String) по имени ресурса возвращает java.net.URL , через который можно получить этот ресурс. getResourceAsStream(String) , как нетрудно догадаться, возвращает java.io.InputStream , через который ресурс можно прочитать.

Имя ресурса представляет собой путь к ресурсу. Есть одна существенная тонкость, а именно – как оно интерпретируется.

Имя может быть абсолютным и относительным. Внешнее отличие – абсолютное имя начинается с символа "/". В первом случае ресурс ищется относительно корня classpath. Т.е. берутся все пути и jar-файлы, входящие в classpath, и ресурс ищется относительно совокупности этих точек. Если же имя относительное – к нему в начало приписывается путь, полученный из пакета текущего класса. Далее поиск ведется как в случае абсолютного имени.

Проще это понять на примерах. Пусть у нас задан classpath: c:\work\myproject\classes;c:\lib\lib.jar . Код примера находится в классе ru.skipy.test.ResourceLoadingTest .

Пример 1 . Мы используем конструкцию getClass().getResource("/images/logo.svg?1") . Поскольку имя начинается с символа "/" – оно считается абсолютным. Поиск ресурса происходит следующим образом:


  • К пути из classpath c:\work\myproject\classes приписывается имя ресурса /images/logo.svg?1 , в результате чего ищется файл c:\work\myproject\classes\images\logo.pn g . Если файл найден – поиск прекращается. Иначе:
  • В jar-файле c:\lib\lib.jar ищется файл /images/logo.svg?1 , причем поиск ведется от корня jar-файла.
  • Пример 2 . Мы используем конструкцию getClass().getResource("res/data.txt") . Поскольку имя не начинается с символа "/" – оно считается относительным. Поиск ресурса происходит следующим образом:
  • К пути из classpath c:\work\myproject\classes приписывается текущий пакет класса, где находится код, – /ru/skipy/test , – и далее имя ресурса res/data.txt , в результате чего ищется файл c:\work\myproject\classes\ru\skipy\test\r es\data.txt . Если файл найден – поиск прекращается. Иначе:
  • В jar-файле c:\lib\lib.jar ищется файл /ru/skipy/test/res/data.txt (имя пакета текущего класса плюс имя ресурса), причем поиск ведется от корня jar-файла.
  • Ну и для того, чтобы ресурс был найден, необходимо обеспечить его существование. Т.е. при сборке приложения (упаковке его в jar-файл) позаботиться о том, чтобы ресурс тоже попал куда надо. Как это сделать – зависит от технологии сборки, многие IDE умеют копировать ресурсы при сборке в ту же точку, куда кладут и скомпилированные классы. При использовании ant это надо предусмотреть в явном виде.

    Вот тут можно скачать полностью рабочий пример, иллюстрирующий оба типа загрузки: . Ресурсы – изображение и текст – располагаются в отдельной директории, при сборке попадают в jar-файл и грузятся один по абсолютному, другой по относительному имени. Пример собирается и запускается через ant , командой ant run он запускается из директории сборки build/classes/ , командой ant run-jar – из собранного jar-файла.

    Вот, где-то так. Вопросы? Комментарии?



    © 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows