Задумываясь о разработке html5 приложения, многим сразу на ум приходит jQuery, или точнее jQueryMobile. И попробовав написать даже самое простенькое приложение используя jQueryMobile, очень легко разочароваться, так как производительность и отзывчивость получившегося html5 приложения куда ниже ожидаемого, и уж совсем его не сравнить с нативными приложениями.
Соответственно, если продолжить идти по пути html5, вы постепенно узнаёте, что тормоза и плохая отзывчивость из-за того, что есть множество тонкостей, например, что jquery далеко не самый быстрый вариант для приложения или по-умолчанию любое нажатие пользователя срабатывает с 300мс задержкой, что ухудшает отзывчивость.
Также важным моментом является есть ли набор готовых типичных компонентов, таких как список, кнопки, боковое меню итд, время на повторную разработку которых нет смысла тратить. Можно добавить еще к этому списку то, что как-то всё таки нужно решить проблему производительности, чтобы конкурировать с нативными приложениями.
И мы, наконец, подходим к самому главному, чтобы не забивать себе голову решением таких проблем, а получить сразу готовый инструмент для разработки быстрых, отзывчивых и функциональных html5 приложений, существует Framework7. Сам я с ним столкнулся совершенно случайно, и удивился тому, насколько он прост в использовании без необходимости искать решения в разных местах, достаточно просто подключить framework7.js.
Стоит отметить, что для работы с Framework7 не нужно использовать какие-то сторонние модули или библиотеки, так как он всё уже содержит:
На сайте есть огромное кол-во примеров (работают в браузере), инструкций и обучающих статей (например, работа Framework7 совместно с AngularJS)
www.idangero.us/framework7
Чтобы далеко не ходить, создадим небольшое приложение-пример, где можно будет посмотреть, как объединить отдельные компоненты фреймворка в единое приложение. Будем использовать slide menu, pull to refresh, infinite scroll, смену material/ios style на лету и огромным списком на 8000 элементов, который не тормозит (virtual list).
Структура приложения довольно простая:
Больше ничего не потребуется, другие библиотеки или фреймворки для создания приложения не нужны. Но при желании можно использовать require.js, angular.js, matreshka.js итд.
В итоге получается очень отзывчивое, легкое и быстрое html5 приложение, которое можно использовать как и где угодно.
Хоть у нас и получилось очень быстрое и легкое приложение, на старых версиях андроид оно всё равно будет недостаточно производительным.
Дело в том, что на версиях андроид до 4.4 используется очень тормозной webview (убедиться в этом можно, например, если на 4.1 андроид поставить chrome beta и запустить приложение в нём, а потом сравнить с тем, что есть во встроенном браузере, то разница в скорости будет очень заметна). Поэтому, если просто запаковать html5 приложение в apk, оно будет использовать именно встроенный тормозной webview.
Только начиная с 5.x андроида, webview обновляется отдельно и базируется на свежем chromium, благодаря чему html5 приложение будет работать быстро и плавно.
Проще говоря, если нужна хорошая производительность от html5 приложения на любых устройствах и любых версиях андроид, нужно чтобы оно работало на chromium движке. Проект, который позволяет это сделать, называется crosswalk и вместо встроенного webview используется свой собственный, который работает на последней версии chromium.
Самый простой способ проверить как ваше html5 приложение будет работать с использованием crosswalk, это установить Intel XDK, создать пустой «Standart HTML5» проект, и заменить в созданном проекте папку www на вашу. Чтобы грузились картинки с удаленных серверов, в файл intelxdk.config.additions.xml нужно добавить:
После этого выбрать Build и нажать на Crosswalk for Android. Приложение будет скомпилировано на удаленном сервере, и спустя несколько минут вы получите ссылку на apk (версия для arm и x86). К минусам можно отнести тот факт, то размер приложения увеличится на ~19мб.
Сайт framework7: www.idangero.us/framework7
Онлайн пример готового приложения: comedian-ant-73047.bitballoon.com (так как онлайн, то немного тормозит загрузка стилей)
Исходники: yadi.sk/d/Quu2VfApgcGXA
Готовые apk файлы, созданные через Intel XDK: yadi.sk/d/marrZA5-gcGuQ
Онлайн пример большинства возможностей (kitchen-sink): www.idangero.us/framework7/kitchen-sink
Тоже самое в material дизайне: poacher-bear-12003.bitballoon.com/kitchen-sink-material/index.html
Соответственно, если продолжить идти по пути html5, вы постепенно узнаёте, что тормоза и плохая отзывчивость из-за того, что есть множество тонкостей, например, что jquery далеко не самый быстрый вариант для приложения или по-умолчанию любое нажатие пользователя срабатывает с 300мс задержкой, что ухудшает отзывчивость.
Также важным моментом является есть ли набор готовых типичных компонентов, таких как список, кнопки, боковое меню итд, время на повторную разработку которых нет смысла тратить. Можно добавить еще к этому списку то, что как-то всё таки нужно решить проблему производительности, чтобы конкурировать с нативными приложениями.
Framework7
И мы, наконец, подходим к самому главному, чтобы не забивать себе голову решением таких проблем, а получить сразу готовый инструмент для разработки быстрых, отзывчивых и функциональных html5 приложений, существует Framework7. Сам я с ним столкнулся совершенно случайно, и удивился тому, насколько он прост в использовании без необходимости искать решения в разных местах, достаточно просто подключить framework7.js.
Стоит отметить, что для работы с Framework7 не нужно использовать какие-то сторонние модули или библиотеки, так как он всё уже содержит:
- High-performance Animation — хочется выделить это отдельно, так как анимации и правда очень быстрые
- fast-clicks — решает проблему задержки 300мс без сторонних библиотек
- Template7 — движок шаблонов, синтаксис как у Handlebars, но меньше весит и скорость до 3х раз быстрее
- Dom7 — более быстрая и прозрачная замена jQuery
- Navigation / Router — множество вариантов переходов и их контроля
- Поддержка стилей, включая частичную поддержку material design
- Огромный список встроенных компонентов, таких как forms, buttons, list view, pull to refresh, infinite scroll, slide menu итд
- Свайпы — встроенные свайпы на все случаи жизни: вызвать меню свайпом, возврат к предыдущему экрану, удалить элемент итд
- И множество других полезных вещей
На сайте есть огромное кол-во примеров (работают в браузере), инструкций и обучающих статей (например, работа Framework7 совместно с AngularJS)
www.idangero.us/framework7
Пример приложения
Чтобы далеко не ходить, создадим небольшое приложение-пример, где можно будет посмотреть, как объединить отдельные компоненты фреймворка в единое приложение. Будем использовать slide menu, pull to refresh, infinite scroll, смену material/ios style на лету и огромным списком на 8000 элементов, который не тормозит (virtual list).
Структура приложения довольно простая:
- index.html — дизайн приложения
- about.html — дизайн другого view
- app.js — файл инициализации и настроек приложения
- css/app.css — этот файл в общем-то не нужен, так как в framework7.css есть уже все настройки дизайна, но можно, например, сменить цвет фона бокового меню
- lib/framework7.js — сам фреймворк
- lib/framework7.css — дизайн всех элементов и компонентов в стиле ios
- lib/framework7.material.css — дизайн всех элементов и компонентов в стиле material
Больше ничего не потребуется, другие библиотеки или фреймворки для создания приложения не нужны. Но при желании можно использовать require.js, angular.js, matreshka.js итд.
index.html
Для начала рассмотрим каркас index.html:
Добавление компонентов очень просто реализовано (для каждого компонента есть инструкция на сайте), например, чтобы добавить pull-to-refresh, достаточно добавить в
класс pull-to-refresh-content, и дизайн стрелочки, которая будет показываться при обновлении:
Теперь надо добавить table view (list view), в котором будет список наших элементов. Для создания коротких списков подойдет List View (Media List итд, список можно создавать статически или динамически):
Но для очень длинных списков требуется выгрузка элементов, которые сейчас не видны на экране, это необходимо для того, чтобы ничего не тормозило, и приложение работало как и нативное. Такий список называется Virtual List, и создается так же просто:
В дальнейшем список надо будет проинициализировать и заполнить в app.js
Сюда же добавим infinite-scroll, который добавляет так же, добавлением одноименного класса, дизайна крутилки и указанием начиная с какого расстояния вызывать infinite-scroll:
Чтобы сменить ios стиль на material стиль и наоборот, добавим 2 кнопки, например, в левом меню:
Позже на класс changestyle повесим обработчик, чтобы реагировал на нажатие и менял css файл на указанный в rel.
<!DOCTYPE html>
<html>
<head>
<!-- Добавляем необходимые meta-тэги -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<title>My App</title>
<!-- подключаем framework7 стили, и добавляем id, чтобы можно было менять стиль на лету -->
<link id="pagestyle" rel="stylesheet" href="lib/framework7.css">
<!-- подключаем наши кастомные стили -->
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<!-- statusbar-overlay для правильной поддержки полноэкранного режима -->
<div class="statusbar-overlay"></div>
<!-- тоже самое для panel -->
<div class="panel-overlay"></div>
<!-- если нужно левое боковое меню с reveal эффектом -->
<div class="panel panel-left panel-reveal">
</div>
<!-- самое главное, добавляем views -->
<div class="views">
<!-- главный экран, должен содержать класс view-main -->
<div class="view view-main">
<!-- если требуется верхняя панель, так же указываем что у нее будет белая тема -->
<div class="navbar theme-white">
</div>
<!-- собственно содержимое страницы, указываем что navbar и toolbar будет зафиксированы -->
<div class="pages navbar-through toolbar-through">
<!-- в data-page указываем название страницы, которое желательно для всех страниц быть разным -->
<div data-page="index" class="page">
<div class="page-content">
</div>
</div>
</div>
<!-- если нужная нижняя панель -->
<div class="toolbar">
<div class="toolbar-inner">
</div>
</div>
</div>
</div>
<!-- подключаем framework7 и наш файл инициализации -->
<script type="text/javascript" src="lib/framework7.js"></script>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
Добавление компонентов очень просто реализовано (для каждого компонента есть инструкция на сайте), например, чтобы добавить pull-to-refresh, достаточно добавить в
<div class="page-content">
</div>
класс pull-to-refresh-content, и дизайн стрелочки, которая будет показываться при обновлении:
<div class="page-content pull-to-refresh-content">
<div class="pull-to-refresh-layer">
<div class="preloader"></div>
<div class="pull-to-refresh-arrow"></div>
</div>
</div>
Теперь надо добавить table view (list view), в котором будет список наших элементов. Для создания коротких списков подойдет List View (Media List итд, список можно создавать статически или динамически):
<div class="list-block media-list"><ul>тут данные</ul></div>
Но для очень длинных списков требуется выгрузка элементов, которые сейчас не видны на экране, это необходимо для того, чтобы ничего не тормозило, и приложение работало как и нативное. Такий список называется Virtual List, и создается так же просто:
<div class="list-block virtual-list media-list">тут оставить пусто</div>
В дальнейшем список надо будет проинициализировать и заполнить в app.js
Сюда же добавим infinite-scroll, который добавляет так же, добавлением одноименного класса, дизайна крутилки и указанием начиная с какого расстояния вызывать infinite-scroll:
<div class="page-content pull-to-refresh-content infinite-scroll" data-distance="100">
<div class="pull-to-refresh-layer">
<div class="preloader"></div>
<div class="pull-to-refresh-arrow"></div>
</div>
<div class="list-block virtual-list media-list"></div>
<div class="infinite-scroll-preloader">
<div class="preloader"></div>
</div>
</div>
Чтобы сменить ios стиль на material стиль и наоборот, добавим 2 кнопки, например, в левом меню:
<div class="list-block left-menu">
<div class="row theme-white" style="width:90%;margin-left: auto;margin-right: auto;">
<div class="col-50">
<a href="#" class="button changestyle" rel="lib/framework7.css">iOS style</a>
</div>
<div class="col-50">
<a href="#" class="button changestyle" rel="lib/framework7.material.css">Android style</a>
</div>
</div>
</div>
Позже на класс changestyle повесим обработчик, чтобы реагировал на нажатие и менял css файл на указанный в rel.
app.js
Теперь рассмотрим файл app.js, в котором производится настройка приложения, инициализация списков итд.
// Инициализируем движок фреймворка
var myApp = new Framework7({
animateNavBackIcon:true,
pushState: true, //при переходе между экранами, чтобы работала кнопка back на android
modalTitle: "MyApp",
modalButtonCancel: "Отмена", //текст Cancel кнопки
swipePanel: 'left', //включаем левого меню свайпом
});
// если запускается на ios, то кнопки back нету, и поэтому можно отключить
if (Framework7.prototype.device.os == "ios")
myApp.params.pushState = false;
// вместо jQuery используем встроенный Dom7, переменную можно назвать $, чтобы было привычнее, но если оставить $$, то в дальнейшем можно будет легко подключить jQuery, если понадобится
var $$ = Dom7;
// по клику меняем css файл, меняя ios и material стиль. Выбор запоминаем в localStorage, чтобы при перезапуске приложения загружался нужный css
$$(".changestyle").click(function() {
$$("#pagestyle").attr("href",$$(this).attr('rel'));
localStorage.setItem("css", $$(this).attr('rel'));
return false;
});
// при первой загрузке загружаем запомненный css
if(localStorage.getItem("css")) {
$$("#pagestyle").attr("href",localStorage.getItem("css"));
}
// инициализируем главную вьюху
var mainView = myApp.addView('.view-main', {
dynamicNavbar: true,
domCache: true, //чтобы навигация работала без сбоев и с запоминанием scroll position в длинных списках
});
// инициализируем и заполняем вирутальный список используя шаблон (один из вариантов использования Template7)
var myList = myApp.virtualList('.list-block.virtual-list', {
items: [
{
id: 1,
title: 'Item 1',
picture: 'http://lorempixel.com/88/88/abstract/1'
},
{
id: 2,
title: 'Item 2',
picture: 'http://lorempixel.com/88/88/abstract/2'
}
],
height:44,
template:
'<li class="contact-item" data-id="{{id}}" >' +
'<a href="about.html" class="item-link">' +
'<div class="item-content">' +
'<div class="item-media"><img src="{{picture}}" width="22"></div>' +
'<div class="item-inner">' +
'<div class="item-title">{{title}}</div>' +
'</div>' +
'</div>' +
'</a>' +
'</li>'
});
// пример функции, которая будет обновлять содержимое виртуального списка
function reloadTable(table, array)
{
table.items = array;
table.update();
}
// заполним виртуальный лист 20 новыми элементами
var itemsArray = [];
function firstInitList(text, count)
{
itemsArray = [];
for (var i = 0; i < count; i++ )
{
itemsArray.push({ id: i, title: text + ' ' + i, picture: 'http://lorempixel.com/88/88/abstract/' + i });
}
}
firstInitList("Item", 20);
reloadTable(myList, itemsArray);
// инициализируем pull-to-refresh
var ptrContent = $$('.pull-to-refresh-content');
ptrContent.on('refresh', function (e) {
// Эмулируем 0.5секундную задержку
setTimeout(function () {
refreshIt();
}, 500);
});
// просто случайные данные для генерации виртуального листа
var authors = ['Beatles', 'Queen', 'Michael Jackson', 'Red Hot Chili Peppers'];
function refreshIt()
{
// первые 10 элементов создадим с надписью Refresh
firstInitList("Refresh", 10);
myList.deleteAllItems();
myList.appendItems(itemsArray);
// остальные 8000 случайным образом
var temparr = [];
for(var i = 0; i<8000; i++)
{
var picURL = 'http://lorempixel.com/88/88/abstract/' + Math.round(Math.random() * 10);
var author = authors[Math.floor(Math.random() * authors.length)];
temparr.push({ id: i, title: author, picture: picURL });
}
myList.appendItems(temparr);
myApp.pullToRefreshDone();
}
// инициализируем infinite-scroll
$$('.infinite-scroll').on('infinite', function () {
loadMore();
});
// флаг
var loading = false;
//прячем крутилку infinite-scroll'а
$$('.infinite-scroll-preloader').hide();
function loadMore()
{
// если уже загружаем данные, то ничего не делаем
if (loading) return;
$$('.infinite-scroll-preloader').show();
// Эмулируем 1 секундную задержку
setTimeout(function () {
for (var i = lastIndex + 1; i <= lastIndex + itemsPerLoad; i++) {
itemsArray.push({ id: i, title: 'Item ' + i, picture: 'http://lorempixel.com/88/88/abstract/1' });
}
reloadTable(myList, itemsArray);
// сбрасываем флаг, после загрузки данных
loading = true;
}, 1000);
}
app.css
// дизайн крутилки для infinite-scroll
.infinite-scroll-preloader {
margin-top:-20px;
margin-bottom: 10px;
text-align: center;
}
.infinite-scroll-preloader .preloader {
width:34px;
height:34px;
}
// сменим цвет фона navbar
.navbar {
border-bottom: none;
background: #2196f3;
color: #ffffff;
}
.navbar a.link {
color: #ffffff;
}
// сменить цвет фона левого меню
.panel, .left-menu .list-button {
background-color: #3f4041;
}
.left-menu .item-link.list-button {
text-align: left;
}
В итоге получается очень отзывчивое, легкое и быстрое html5 приложение, которое можно использовать как и где угодно.
Ускоряем html5 приложения на старых версия android. Crosswalk
Хоть у нас и получилось очень быстрое и легкое приложение, на старых версиях андроид оно всё равно будет недостаточно производительным.
Дело в том, что на версиях андроид до 4.4 используется очень тормозной webview (убедиться в этом можно, например, если на 4.1 андроид поставить chrome beta и запустить приложение в нём, а потом сравнить с тем, что есть во встроенном браузере, то разница в скорости будет очень заметна). Поэтому, если просто запаковать html5 приложение в apk, оно будет использовать именно встроенный тормозной webview.
Только начиная с 5.x андроида, webview обновляется отдельно и базируется на свежем chromium, благодаря чему html5 приложение будет работать быстро и плавно.
Проще говоря, если нужна хорошая производительность от html5 приложения на любых устройствах и любых версиях андроид, нужно чтобы оно работало на chromium движке. Проект, который позволяет это сделать, называется crosswalk и вместо встроенного webview используется свой собственный, который работает на последней версии chromium.
Самый простой способ проверить как ваше html5 приложение будет работать с использованием crosswalk, это установить Intel XDK, создать пустой «Standart HTML5» проект, и заменить в созданном проекте папку www на вашу. Чтобы грузились картинки с удаленных серверов, в файл intelxdk.config.additions.xml нужно добавить:
<access origin="*" />
После этого выбрать Build и нажать на Crosswalk for Android. Приложение будет скомпилировано на удаленном сервере, и спустя несколько минут вы получите ссылку на apk (версия для arm и x86). К минусам можно отнести тот факт, то размер приложения увеличится на ~19мб.
Сайт framework7: www.idangero.us/framework7
Онлайн пример готового приложения: comedian-ant-73047.bitballoon.com (так как онлайн, то немного тормозит загрузка стилей)
Исходники: yadi.sk/d/Quu2VfApgcGXA
Готовые apk файлы, созданные через Intel XDK: yadi.sk/d/marrZA5-gcGuQ
Онлайн пример большинства возможностей (kitchen-sink): www.idangero.us/framework7/kitchen-sink
Тоже самое в material дизайне: poacher-bear-12003.bitballoon.com/kitchen-sink-material/index.html
Комментарии (15)
rework
14.05.2015 10:10+1Спасибо за статью. Очень интересно и главное во время, как раз пришла задача по разработке приложения на phoneGap, думаю попробую этот фреймворк7.
hudson
14.05.2015 12:24+1Спасибо! Фреймворк мне как таковой оказался не очень интересен, но узнал про Intel XDK. Век живи — век учись!
Blumfontein
14.05.2015 13:17+1А что вы используете и почему фреймворк оказался неинтересн?
hudson
14.05.2015 21:31+1Пообщался с командой, сказали что я дурак и штука нужная )) Надо наверное на примерах попробовать.
bulletproofcupid
14.05.2015 16:05+1Спасибо, надо будет глянуть. Плотно использовал onsen, но этот, похоже и пошустрее и плюшками радует. Раздел «killer features» на сайте впечатлил.
Ti_webdev
18.05.2015 06:45Странно, что никто не упомянул про более популярный Ionic Framework, инфраструктура которого гораздо богаче.
dDoom
Таких множество — мне понравился onsen.io и goratchet.com Последнии прижился как основной, на нем все и разрабатываю.
Shannon Автор
Возможно мой пример плохо отобразил все возможности framework7, поэтому в конец статьи добавил ссылки на kitchen-sink (отдельно в material дизайне), с почти (много чего добавляется и не успевает попасть в kitchen-sink, но даже и то что сейчас добавлено впечатляет) полным перечнем возможностей собранных в одном приложении от автора
Тут всё таки стоит добавить, что по числу готовых компонентов (что для меня оказалось решаюшив фактором в пользу framework7 вместо ratchet), разнообразных killer features, и даже подробной и удобной документации, аутентичности анимаций, и результирующей скорости приложения — framework7 оказался пока вне конкуренции среди подобных фреймворков