План
Как по мне, то материал проще усваивать небольшими порциями. Поэтому мне нужно указать некое содержание:
- Введение
- Логика приложения
- Подготовка к релизу
- Исправление ошибок
- Оптимизация jQuery
- Оптимизация ресурсов
- Семантическое версионирование
- Иконки
- Сжатие
- Распространение
- Итоги
К слову, недавно вышел новый релиз node-webkit, который исправляет проблему работы с кодировкой. Всем нужно обновиться и радоваться тому, что приложения теперь нормально работают с кодировкой :)
Исправление ошибок
Прошу прощения у тебя, мой читатель, я попытался тебя обмануть, хотя и не сознательно. К великому сожалению я каким-то чудесным образом написал переключатель иконки прямиком в условии, что не позволяет ей нормально переключаться. Исправляется это в файле windowEvents
и совсем просто:
Было:
$('#window-resize').on("click", function() {
if ($( this ).hasClass('maximize')) {
...
$( this ).children('i').toggleClass('icon-toolbar-maximize icon-toolbar-minimize');
} else {
...
};
});
Стало:
$('#window-resize').on("click", function() {
if ($( this ).hasClass('maximize')) {
...
};
$( this ).children('i').toggleClass('icon-toolbar-maximize icon-toolbar-minimize');
});
Оптимизация jQuery
Если вспомнить предыдущую статью из этой серии, то можно заметить, что у нас в файлах содержится довольно много jQuery-запросов в виде:
$('#editor-input')
$('#editor-preview')
И как вы уже догадались — это не хорошо. Каждый новый jQuery-запрос делает повторный поиск по DOM-дереву. В нашем случае это не слишком-то важно, так как приложение маленькое, и количество запросов тоже не велико. Но, в теории, если наше приложение будет разрастаться, то приложение будет работать медленнее. Поэтому заменим все повторяющиеся запросы на jQuery переменные и объявим их в верхушке файла:
Файл windowEvents
и editor
:
...
$ = global.jQuery,
$editorInput = $('#editor-input'),
$editorPreview = $('#editor-preview');
Помимо jQuery-запросов, у нас имеется событие клика на кнопку-переключатель полноэкранного режима, где применяется jQuery-метод .children()
, который работает куда медленнее, чем его «отец» метод .find()
примерно в три раза. Путём логических размышлений и проведения теста, принимаем решение убить подлеца!
$('#window-resize').on("click", function() {
if ($( this ).hasClass('maximize')) {
...
};
$( this ).find('i').toggleClass('icon-toolbar-maximize icon-toolbar-minimize');
});
Помимо этого, говорят, что одной из так называемых «best practice» является следующее утверждение:
Когда цепочка вызовов метода слишком длинная и не помещается в одну строку (больше 80 символов), следует писать один вызов метода на строке. При этом соблюдать контекстную иерархию отступов (дополнительный отступ).
К счастью, такое место у нас одно, и с ним мы уже работали выше:
$('#window-resize').on("click", function() {
if ($( this ).hasClass('maximize')) {
...
};
$( this )
.find('i')
.toggleClass('icon-toolbar-maximize icon-toolbar-minimize');
});
Внимательный, матёрый JavaScript программист заметит, что у меня используются разные кавычки ('string
и "string"
). В своё оправдание скажу лишь одно — это всего лишь привычка. Мне нравится идеология того, что всюду (почти) нужно использовать один вид кавычек, но куда больше мне нравится следующая модель:
- Одиночные кавычки всюду, кроме указанных ниже мест.
- Двойные кавычки для указания событий.
Однако, нужно придерживаться рекомендаций, и поэтому я борюсь с этим недугом. Следствием этой борьбы будет приведение к единому стилю написания кавычек и в этом проекте.
Увы, иногда так бывает, что увлекаешься и как-то не до соблюдения стилей. Но вскоре я всё таки переделаю Raptorius, чтобы он успевал за мной и проверял мой код на соответствие стандартам.
На этом оптимизацию jQuery можно завершить. Конечно, если вы всё ещё не хотите его выбросить из проекта или заменить более «лёгким» аналогом.
Все изменения в коде, на этом этапе, можно посмотреть в этом коммите на GitHub.
Оптимизация ресурсов
В этой части статьи нужно всего лишь оптимизировать ресурсы приложения.
На что следует обратить внимание:
- Картинки и шрифты
- Лишние ресурсы
По ясным причинам, удалять из репозитория Less файлы я не буду, а вот если бы наш блокнот отправлялся в продакшен, то сделать это было бы неплохо.
Также можно осуществить минификацию скриптов и стилей, но никаких преимуществ это не даст.
Семантическое версионирование
Не забывайте следовать семантическому версионированию и старайтесь своевременно обновлять версию приложения.
В нашем случае следует увеличить ПАТЧ, так как мы сделали обратно совместимые исправления.
Все изменения в коде, на этом этапе, можно посмотреть в этом коммите на GitHub.
Попутно стоит напомнить о том, что можно встроить в приложение напоминалку о выходе новых версий приложения, например, по средствам пакета github-update-checker, если основной репозиторий у вас находится на GitHub.
Иконки
Сейчас NodePad у нас безликий — это плохо, так как он имеет стандартную иконку поставляемую node-webkit. А вдруг завтра все начнут использовать node-webkit? NodePad потеряется среди остальных приложений! Так нельзя.
Автоматический способ
Проще некуда, нужно:
- Создать директорию icons вне
app/
, чтобы лишние файлы не были в программе при сборке. - Добавить в директорию
icons/
два файла:icon.ico
(Windows) иicon.icns
(OS X). - Слегка изменить Gruntfile.
Превратить PNG в ico и icns можно, используя ICONVERT ICONS. Но, как это известно дизайнерам, вручную куда лучше — можно контролировать каждый пиксел.
Итак, дополнение файла настроек Grunt будет содержать всего две строки:
...
macIcns: './icons/icon.icns',
winIco: './icons/icon.ico'
...
Теперь NodePad обрел лицо в Windows:
И похорошел в OS X:
Для добавления иконки в Linux версию приложения пока что автоматического метода нет.
Ручной способ
На этот раз всё скучнее и дольше. При этом необходимо иметь все три платформы под рукой.
Windows
Придётся скачать Resource Hacker и прочитать небольшую заметку, в которой говорится буквально следующее:
- Открыть exe файл
- Перейти в директорию
icon -> 1 -> ...
- Выбрать в меню заменить ресурс и найти предварительно созданный ico файл
- Сохранить exe
OS X
С иконкой для OS X куда интереснее.
- Превращаем PNG в icns файл.
- Перенести файл в
.app/Contents/Resources
и переименовать его вnw.icns
. - Указать иконку в файле
.app/Contents/Info.plist
, если вы не хотите переименовывать файл.
Linux
Для Linux нужно курить этот мануал.
Сжатие
Как и говорилось ранее, размер NodePad внушающий:
- Windows: ~65МБ
- OS X: ~90МБ (без учета веса иконки)
- Linux: ~100МБ
Если сказать, что я офигел от цифр, то это не будет передавать моё эмоциональное состояние :)
И на этой грустной ноте приходит на помощь — UPX.
UPX — это упаковщик исполняемых файлов, который поддерживает множество форматов, включая COM, EXE, SYS. После упаковки файлы занимают минимум места на диске, но платой за это будет распаковка приложения непосредственно в память при запуске.
Если вы готовы заплатить снижением скорости запуска приложения, то результаты получаются неплохие (настройки UPX по умолчанию):
NodePad.exe
Исходный размер — ~47МБ. После UPX — ~18МБ.
Согласитесь, неплохо. Однако, бесполезно. Я не вижу пользы даже в 100МБ, если это снижает скорость запуска приложения.
Если размер вашего приложения будет большим, то целесообразнее не упаковывать приложение в .zip и далее действовать по стандартной схеме, а положить файлы приложения (включая package.json) рядом с nw. При запуске nw выполняется поиск package.json файла приложения и, как следствие, его запуск. Нужно также учесть, что на OSX это будет тот же каталог, на одном уровне, с node-webkit.app
.
Распространение
Разумеется, NodePad нужно распространять среди других пользователей, чтобы получить хоть какое-то удовлетворение от проделанной работы. Неважно, будет ли это обратная связь по найденным ошибкам, предложение о модификации и улучшении существующего функционала или же вовсе банальное спасибо (не исключен также вариант с гневными отзывами о том, что больше писать приложения лучше не стоит и вообще пора идти в уборщики или по новой заканчивать школу).
Итого, у нас есть несколько путей распространения программы в виде:
- Исходников проекта.
- Собранного проекта (скомпилированного, если так угодно), то есть готово к использованию приложения.
- Установщика.
Давайте подробнее рассмотрим все три способа.
Распространение исходников
Этот вариант я предлагаю сразу отнести в корзину для «неудачных идей». Если рассмотреть все плюсы такого вида распространения, то их ничтожное количество будет несоизмеримо с минусами.
Рассматривать такой вид распространения можно только в том случае, если приложение ориентировано на других разработчиков, которые смогут собрать его сами, и, конечно же, при наличии отличной документации.
Распространение приложения
Вариант с распространением предварительно собранного приложения под все поддерживаемые операционные системы выглядит куда лучше, хотя бы тем, что им можно пользоваться.
Однако, пользователю вашего приложения придётся самостоятельно копировать все файлы приложения в какую-то директорию, отличную от «Downloads». В противном случае, при следующей чистке ОС возможен вариант того, что ваше приложение полетит в корзину. При этом пользователь должен создать ярлык для быстрого запуска приложения с рабочего стола, иначе, опять таки, ему придётся каждый раз переходить в директорию, где располагается исполняемый файл, и запускать.
Помимо всех этих лишних телодвижений, если приложение утратит актуальность, пользователю придётся самому удалять все файлы приложения:
- Директория приложения (например, в Windows, такая:
c:\Program Files (x86)\NodePad\
). - Директория рабочих файлов (что-то похожее на:
c:\Users\UserName\AppData\Local\NodePad\
). - Прочие директории, которые необходимы разработчику.
- Возможно, ключи реестра, если приложению такие были необходимы.
А если ещё есть какие-то зависимые внешние библиотеки, то... ой, даже думать об этом не хочу.
Мне такой вариант не нравится.
Распространение установщика
Пожалуй, это самый оправданный вариант распространения приложения. Рассмотрим кратко его плюсы и минусы:
Плюсы
- Пользователь загружает только один исполняемый файл, в котором содержится всё необходимое для работы приложения.
- Загрузил — Установил — Пользуйся.
- Если приложение потеряло актуальность, то удаление происходит штатным способом, то есть по стандартам ОС, используя настроенный разработчиком инсталлятор.
- Возможно создание установщика — загрузчика приложения, когда установщик знает откуда загружать последнюю версию приложения.
Минусы
- Разработчик должен сделать такой установщик и правильно его настроить под каждую ОС.
В любом случае выбор за вами. И если этот выбор пал на создание установщика, то оставлю ссылку, по которой приведено некоторое количество установщиков на любой вкус. Обращаю ваше внимание на ту часть, где указаны кроссплатформенные решения и, в частности, IzPack.
Итоги
Вот и подошёл к концу небольшой цикл статей, в котором мы так упорно создавали наше первое node-webkit приложение. Напомню, что основной целью этого цикла было ознакомление с технологиями создания нативного приложения на Node.js, используя node-webkit.
На достигнутом останавливаться я не советую, так для веб-разработчиков сейчас доступно огромное количество инструментов, которые нужно попробовать и, возможно, даже начать использовать.
В заключении хочу привести скромный список ресурсов, с которыми вы можете ознакомиться для дальнейшего изучения node-webkit:
Статьи и презентации
- Введение в HTML5 приложения для настольных систем, используя Node-Webkit
- Серия статей (6 штук) по построению node-webkit приложений
- Создание простейшего Twitter-клиента для отображения потока твитов
- Создание чата на node-webkit, Firebase и AngularJS
- Построение настольного приложения с помощью node-webkit
- Создание приложения для детского сада XLS to PDF
- Что вы должны знать, перед тем как начать использовать node-webkit
- Веб-приложения в мире настольных приложений с node-webkit
Видео
- Доклад про node-webkit на октябрьском Линуксфесте в Петербурге
- от WebApp к DesktopApp, используя Node-Webkit
- Мини-серия видео о том, как построить своё HTML5 настольное приложение, используя node-webkit
Обязательно обратите внимание на великолепную шпаргалку от Julien Le Coupanec, в которой можно найти уйму информации о node-webkit, буквально на нескольких страницах А4. Если вы серьёзно решите заниматься разработкой на этой платформе, то советую распечатать.
Внимание
Готовое приложение можно найти в репозитории на GitHub по этой ссылке.
UPD: Обновление (1.03.2015)
Для упрощения сборки проекта можно использовать специальную утилиту. Подробнее в мини-обзоре.