Шаблонизация на стороне клиента

Шаблонизация это привычное явление, если говорить о серверной части web-приложения. Шаблоны, обрабатывающиеся на стороне сервера, преобразуются в html-код, которой отдаётся клиенту, в качестве которого чаще всего выступает браузер. В таком подходе есть свои недостатки.

Плюсы и минусы

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

Чтобы избавиться от этих проблем, можно отдавать с сервера данные, не обёрнутые в html, а сериализованные в json или xml, оставив заботу о внешнем виде приложения полностью на клиентскую часть. При этом подходе неплохо бы использовать механизм шаблонизации на стороне клиента, чтобы отделить поведение приложения от его внешнего вида. Если в качестве клиента служит браузер, то этот механизм можно организовать при помощи JavaScript. В таком подходе тоже есть свои недостатки. Во-первых, генерируемый таким образом контент не будет индексироватья, во-вторых код шаблонов, если он содержится прямо в коде html-странице, сделает её не валидной, и многие редакторы кода или IDE будут ругаться и плохо работать с кодом таких шаблонов.

Пример

Давайте рассмотрим в качестве примера следующий случай: на сервере у нас расположена информация о популярности языков программирования (по данным TIOBE Software BV) и нам необходимо отдать её клиентской части приложения, для последующей визуализации. Предусмотрим так же возможность локализации. Для простоты расположим данные о рейтинге языков программирования и тексты на английских и русских языках в файлах в формате json.

Содержимое файла json/data.json:

{
	"programmingLanguages": [
		{"currentPosition": 1, "previousPosition": 1, "programmingLanguage": "C"},
		{"currentPosition": 2, "previousPosition": 2, "programmingLanguage": "Java"},
		{"currentPosition": 3, "previousPosition": 3, "programmingLanguage": "Objective-C"},
		{"currentPosition": 4, "previousPosition": 4, "programmingLanguage": "C++"},
		{"currentPosition": 5, "previousPosition": 6, "programmingLanguage": "C#"},
		{"currentPosition": 6, "previousPosition": 5, "programmingLanguage": "PHP"},
		{"currentPosition": 7, "previousPosition": 7, "programmingLanguage": "(Visual) Basic"},
		{"currentPosition": 8, "previousPosition": 8, "programmingLanguage": "Python"},
		{"currentPosition": 9, "previousPosition": 23, "programmingLanguage": "Transact-SQL"},
		{"currentPosition": 10, "previousPosition": 11, "programmingLanguage": "JavaScript"}
	],
 
	"languages": [
		{"name": "ru", "file": "json/ru.json"},
		{"name": "en", "file": "json/en.json"}
	]
}

Содержимое файла json/ru.json:

{
	"title": "Рейтинг языков программирования",
	"position": "Позиция",
	"currentDate": "Ноябрь 2013",
	"previousDate": "Ноябрь 2012",
	"programmingLanguage": "Язык программирования"
}

Содержимое файла json/en.json выглядит аналогично содержимому файла ru.json.

В качестве шаблонизатора возьмём библиотеку doT.js. Шаблоны расположим прямо в коде странице в тегах script.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Рейтинг языков программирования</title>
<link rel="stylesheet" href="style.css" />
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="js/doT.min.js"></script>
<script id="select-languages-template" type="text/x-dot-template">
<select id="select-language">
	{{~ it.languages :lang}}
		<option value="{{=lang.file}}">{{=lang.name}}</option>
	{{~}}
</select>
</script>
<script id="header-row-template" type="text/x-dot-template">
<tr>
	<th colspan="2">
		{{=it.lang.position}}
	</th>
	<th rowspan="2">{{=it.lang.programmingLanguage}}</th>
</tr>
<tr>
	<th>{{=it.lang.currentDate}}</th>
	<th>{{=it.lang.previousDate}}</th>	
</tr>
</script>
<script id="row-template" type="text/x-dot-template">
<tr>
	<td>{{=element.currentPosition}}</td>
	<td>{{=element.previousPosition}}</td>
	<td>{{=element.programmingLanguage}}</td>
</tr>
</script>
<script id="global-template" type="text/x-dot-template">
<div id="wrapper">
	<h3>{{=it.lang.title}}</h3>
	<table>
		{{#def.headerRow}}
		{{~ it.data :element}}
			{{#def.row}}
		{{~}}
	</table>
</div>
</script>
<script type="text/javascript" src="js/client-side-templating-example.js"></script>
</head>
<body>
</body>
</html>

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

На этом всё. Теперь вы имеете представление о том, что такое клиентская шаблонизация и зачем она нужна. Как всегда успехов вам!

* Примечание: сhrome отказывается загружать локальный файл ajax’ом, поэтому для запуска примера в этом браузере воспользуйтесь http-сервером, например, apach’ем.

Демо | Исходники

  • Олег Оскольский

    AngularJS.

    • Mustache туда же. Да сейчас всё через клиент делается, и давно пора.