Но, как и всё вокруг, наш веб-сайт имеет тенденцию разрастаться и видоизменяться. Из одной веб-страницы мы делаем другую копированием соответствующего HTML-файла и изменением его содержимого, и этих файлов становится всё больше и больше. Рано или поздно мы заметим тревожные симптомы:
- различий внутри двух близких по времени файлов наберётся дай бог процентов на 10;
- HTML-код на сайте от страницы к странице становится всё более и более разнородным, потому что мы узнаём новые приёмы, а старый код исправлять лень или некогда;
- всё труднее поддерживать единообразное оформление, например, чтобы изменить шапку страниц или название одного пункта навигации, приходится править кучу HTML-файлов, валяющихся на сайте с начала времён.
К сожалению, это прозрение приходит с осознанием того, что придётся переделать пару дюжин уже существующих и пусть не вписывающихся в ваше новое видение, но хорошо работающих веб-страниц. Что ж, на это надо потратить время - оно того стоит.
Будем использовать модельный пример. Пусть у нас есть сайт, стоящий из трёх веб-страниц, соответствующие HTML-файлы которых выглядят так:
Файл index.html
<html>
<title>Главная страница</title>
<body>
<div>Шапка сайта</div>
<div><a href="first.html">На первую страницу</a> | <a href="second.html">На вторую страницу</a><div>
</body>
</html>
<title>Главная страница</title>
<body>
<div>Шапка сайта</div>
<div><a href="first.html">На первую страницу</a> | <a href="second.html">На вторую страницу</a><div>
</body>
</html>
Файл first.html
<html>
<title>Первая страница</title>
<body>
<div>Шапка сайта</div>
<div><a href="/">На главную</a> | <a href="second.html">На вторую страницу</a></div>
<div>Содержимое первой страницы</div>
</body>
</html>
<title>Первая страница</title>
<body>
<div>Шапка сайта</div>
<div><a href="/">На главную</a> | <a href="second.html">На вторую страницу</a></div>
<div>Содержимое первой страницы</div>
</body>
</html>
Файл second.html
<html>
<title>Вторая страница</title>
<body>
<div>Шапка сайта</div>
<div><a href="/">На главную</a> | <a href="first.html">На первую страницу</a></div>
<div>Содержимое второй страницы</div>
</body>
</html>
<title>Вторая страница</title>
<body>
<div>Шапка сайта</div>
<div><a href="/">На главную</a> | <a href="first.html">На первую страницу</a></div>
<div>Содержимое второй страницы</div>
</body>
</html>
Итак, приступим.
Первым делом надо произвести аудит наших наработок и выделить те части, которые должны остаться неизменными от страницы к странице. Это наверняка будет шапка сайта, меню, оформление и т.п. Дальше нужно будет выбрать путь из множества вариантов, доступных (или потенциально доступных) веб-разработчику.
Например, можно творчески использовать тег <iframe>, выделив шапку сайта и меню в отдельный фрейм. Наш модельный сайт в этом случае может выглядеть так:
Файл header.html
<html>
<body>
<div>Шапка сайта</div>
<div>
<a target="_top" href="/">На главную</a> |
<a target="_top" href="first.html">На первую страницу</a> |
<a target="_top" href="second.html">На вторую страницу</a>
</div>
</body>
</html>
<body>
<div>Шапка сайта</div>
<div>
<a target="_top" href="/">На главную</a> |
<a target="_top" href="first.html">На первую страницу</a> |
<a target="_top" href="second.html">На вторую страницу</a>
</div>
</body>
</html>
Файл index.html
<html>
<title>Главная страница</title>
<body>
<div><iframe src="header.html"></div>
</body>
</html>
<title>Главная страница</title>
<body>
<div><iframe src="header.html"></div>
</body>
</html>
Файл first.html
<html>
<title>Первая страница</title>
<body>
<div><iframe src="header.html"></div>
<div>Содержимое первой страницы</div>
</body>
</html>
<title>Первая страница</title>
<body>
<div><iframe src="header.html"></div>
<div>Содержимое первой страницы</div>
</body>
</html>
Файл second.html
<html>
<title>Вторая страница</title>
<body>
<div><iframe src="header.html"></div>
<div>Содержимое второй страницы</div>
</body>
</html>
<title>Вторая страница</title>
<body>
<div><iframe src="header.html"></div>
<div>Содержимое второй страницы</div>
</body>
</html>
Теперь, если мы захотим вместо "Шапка сайта" написать "Кепка сайта", нам не придётся править все три HTML-файла, достаточно поменять лишь страницу header.html. Но на самом деле это - не очень хороший подход. Так не удастся избавиться от большей части однообразного содержимого HTML-файлов: заголовков, разметки и т.п. Поэтому более разумным вариантом представляется использование шаблонов.
Что такое шаблон в веб-разработке? Ближайшим его аналогом в материальном мире является бланк. Да-да, та самая отпечатанная типографским способом разлинованная бумажка, вписав в которую свои ФИО и другие реквизиты получаешь заявление на загранпаспорт, квитанцию о переводе денежных средств, товарную накладную и т.п. Так что при этом подходе нам понадобится разработать некую заготовку, в которую останется лишь вписать в нужный момент нужные данные. Но кто будет эти данные вписывать?
Тут опять-таки возможны два варианта:
- наполнять шаблон данными на сервере и отдавать клиенту готовый документ;
- передать шаблон и данные клиенту, и пусть его браузер сам их компонует как хочет.
Первый путь предполагает наличие на стороне сервера какого-то механизма для обработки клиентских запросов. Стоит отметить, что в наше цивилизованное время сами веб-серверы научились в какой-то мере производить необходимые манипуляции со страницами перед отправкой их клиенту. Мы имеем в виду технологию Server Side Includes (SSI).
В частности, наш модельный пример с использованием SSI принимает вид:
Файл header.shtml
<div>Шапка сайта</div>
<div>
<a href="/">На главную</a> |
<a href="first.shtml">На первую страницу</a> |
<a href="second.shtml">На вторую страницу</a>
</div>
<div>
<a href="/">На главную</a> |
<a href="first.shtml">На первую страницу</a> |
<a href="second.shtml">На вторую страницу</a>
</div>
Файл index.shtml
<html>
<title>Главная страница</title>
<body>
<!--#include file="header.shtml"-->
</body>
</html>
<title>Главная страница</title>
<body>
<!--#include file="header.shtml"-->
</body>
</html>
Файл first.shtml
<html>
<title>Первая страница</title>
<body>
<!--#include file="header.shtml"-->
<div>Содержимое первой страницы</div>
</body>
</html>
<title>Первая страница</title>
<body>
<!--#include file="header.shtml"-->
<div>Содержимое первой страницы</div>
</body>
</html>
Файл second.shtml
<html>
<title>Вторая страница</title>
<body>
<!--#include file="header.shtml"-->
<div>Содержимое второй страницы</div>
</body>
</html>
<title>Вторая страница</title>
<body>
<!--#include file="header.shtml"-->
<div>Содержимое второй страницы</div>
</body>
</html>
Как видим, с помощью этого механизма можно собирать веб-страницы из разрозненных частей, избегая таким образом избыточного их дублирования. А с учетом наличия средств, обеспечивающих ветвление, SSI оказывается безусловно интересным вариантом в некоторых случаях.
Более тонкой настройке поддаются программы или скрипты для обработки шаблонов, написанные на каком-нибудь подходящем языке программирования. Это может быть PHP, Python, ASP, node.js, черт, дьявол, да всё что угодно вплоть до bash-скриптов. У каждого из этих языков есть свои достаточно мощные инструменты и модули для работы с шаблонами. Мы не будем углубляться в эти дебри, а покажем на нашем модельном примере сам принцип обработки шаблонов с помощью серверных приложений.
Пусть у нас на сайте установлен Python. Перепишем наш пример следующим образом:
Файл template.html
<html>
<title>%(title)s</title>
<body>
<div>Шапка сайта</div>
<div>
<a href="/">На главную</a> |
<a href="first.py">На первую страницу</a> |
<a href="second.py">На вторую страницу</a>
</div>
<div>%(content)s</div>
</body>
</html>
<title>%(title)s</title>
<body>
<div>Шапка сайта</div>
<div>
<a href="/">На главную</a> |
<a href="first.py">На первую страницу</a> |
<a href="second.py">На вторую страницу</a>
</div>
<div>%(content)s</div>
</body>
</html>
Файл index.py
from mod_python import Cookie, apache
def index(req):
return open('template.html').read() % \
{
'title' : 'Главная страница',
'content' : ''
}
def index(req):
return open('template.html').read() % \
{
'title' : 'Главная страница',
'content' : ''
}
Файл first.py
from mod_python import Cookie, apache
def index(req):
return open('template.html').read() % \
{
'title' : 'Первая страница',
'content' : 'Содержимое первой страницы'
}
def index(req):
return open('template.html').read() % \
{
'title' : 'Первая страница',
'content' : 'Содержимое первой страницы'
}
Файл second.py
from mod_python import Cookie, apache
def index(req):
return open('template.html').read() % \
{
'title' : 'Вторая страница',
'content' : 'Содержимое второй страницы'
}
def index(req):
return open('template.html').read() % \
{
'title' : 'Вторая страница',
'content' : 'Содержимое второй страницы'
}
Как видим, в этом примере данные удалось полностью отвязать от их отображения, что является несомненным плюсом. Правда, при этом увеличилась нагрузка на сервер и пришлось изучить Python, но оно того стоит. Весь HTML код оказался в файле шаблона, и если мы, скажем, захотим сверстать наш сайт как-то по-другому, нам не придётся переписывать кучу файлов HTML. Конечно, большое множество изменений, связанных с оформлением, можно сделать с помощью стилевых файлов. Но, скажем, подключить какой-нибудь javascript или установить тег META с помощью CSS, насколько я в курсе, не получится.
Второй путь - предоставить браузеру на стороне клиента строить из шаблона и данных отображаемую у клиента страницу - проще всего реализуется, как мне кажется, с помощью технологии по имени XSLT. В этом случае мы передаем клиенту данные и рецепт, по которому ему предстоит из данных собрать итоговую страницу. Проиллюстрируем этот подход на нашем многострадальном модельном примере:
Файл template.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<html>
<title><xsl:value-of select="title"/></title>
<body>
<div>Шапка сайта</div>
<div>
<a href="/">На главную</a> |
<a href="first.xml">На первую страницу</a> |
<a href="second.xml">На вторую страницу</a>
</div>
<div><xsl:value-of select="content"/></div>
</body>
</html>
</xsl:template>
<xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<html>
<title><xsl:value-of select="title"/></title>
<body>
<div>Шапка сайта</div>
<div>
<a href="/">На главную</a> |
<a href="first.xml">На первую страницу</a> |
<a href="second.xml">На вторую страницу</a>
</div>
<div><xsl:value-of select="content"/></div>
</body>
</html>
</xsl:template>
<xsl:stylesheet>
Файл index.xml
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="template.xsl"?>
<root>
<title>Главная страница</title>
<content/>
</root>
<?xml-stylesheet type="text/xsl" href="template.xsl"?>
<root>
<title>Главная страница</title>
<content/>
</root>
Файл first.xml
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="template.xsl"?>
<root>
<title>Первая страница</title>
<content>Содержимое первой страницы</content>
</root>
<?xml-stylesheet type="text/xsl" href="template.xsl"?>
<root>
<title>Первая страница</title>
<content>Содержимое первой страницы</content>
</root>
Файл second.xml
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="template.xsl"?>
<root>
<title>Вторая страница</title>
<content>Содержимое второй страницы</content>
</root>
<?xml-stylesheet type="text/xsl" href="template.xsl"?>
<root>
<title>Вторая страница</title>
<content>Содержимое второй страницы</content>
</root>
Этот подход лично мне импонирует по многим причинам. Во-первых, с подобного сайта легко можно брать и обрабатывать данные машинным способом. Во-вторых, сервер не нагружается задачей превращения шаблона в итоговую страницу. В-третьих, данные опять-таки полностью отделены от оформления. Но тут есть пара подводных камней, один большой и один поменьше.
Как оказалось, не все браузеры поддерживают эту технологию. Например, браузер, встроенный в Android, до 4-й версии XML+XSLT не понимал. И, самое главное: сайты, сверстанные с использованием XML+XSLT, крайне неохотно индексируются поисковиками. То есть, боты преобразованием XSLT не заморачиваются. Можно слегка поправить ситуацию, если привести XML-файлы с данными к виду "почти HTML", но это - явный костыль.
Резюмирую. Задача уменьшения количества повторений одного и того же HTML кода по всему сайту в принципе решаема, причем путей её решения может быть несколько. Все они, конечно, требуют дополнительных знаний, но прогрессом, как известно, движет лень, и вышеупомянутые технологии - лишнее тому доказательство.
Комментариев нет:
Отправить комментарий