Pull to refresh
288.78
Конференции Олега Бунина (Онтико)
Конференции Олега Бунина

Как сделать кроссплатформенное десктопное приложение на базе веб-технологий

Reading time15 min
Views43K


Дмитрий Дудин (xbSoftware)


Сегодня я вам расскажу про технологию nw.js, большинство слайдов моей презентации будет посвящено ей. Это технология позволяет разрабатывать десктопные приложения и писать их на html, javascript и css. Причем приложение будет кроссплатформенное — под Windows, Linux и Mac. Можно их сбилдить и они будут иметь доступ к графическому интерфейсу системы, т.е. смогут еще работать с менюшками и т.д.

Меня зовут Дима (@nedudi), я работаю в компании XB Software, я из Минска.

Мы делаем всякие Javascript компоненты webix для админок, т.е. для больших объемов данных — можете найти и посмотреть. Еще мы занимаемся аутсорсом, кроме этого, я пишу блог html5.by. Еще у нас в Минске есть фронтенд-сообщество 4front, которое мы организуем, и еще — мы раз в полгода проводим «What the Hack» — это такое мероприятие, где мы делаем бесполезные для жизни хаки, т.е. антистартаперское, но очень крутое.

Перейдем к теме.


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

Допустим, я хочу написать приложение на веб-технологиях и я хочу, чтобы оно работало по принципу десктопного приложения. Какие барьеры у меня есть? Я их буду выражать как «я хочу»:

  • Я хочу, чтобы веб приложение имело доступ к файловой системе, системным процессам, буферу обмена, каким-то сочетаниям клавиш и т.д.
  • Хочу, чтобы оно могло работать в фоне, могло запускаться при старте системы, могло работать полностью автономно онлайн, при этом, не заботясь о том, что оно работает оффлайн.
  • Хочу, чтобы оно не спрашивало каждый раз доступ к камере и микрофону, когда человек его запускает.
  • Хочу использовать в своем приложении Web GL, Web Audio, Web RTC, все новые веб API, и при этом быть уверенным, что они будут работать на одном и том же движке. Т.е. движок, который я установил, а не который есть у человека в браузере.
  • Хочу, чтобы оно могло создавать системные менюшки, окна, всякие иконки в трее, могло ими управлять.
  • Хочу с помощью приложения, допустим, делать полноэкранные скриншоты.
  • Хочу пользоваться системной нотификацией.
  • Хочу делать кроссдоменные запросы, менять UserAgent, загружать Google во фрейме. Что это такое — некоторые сайты, когда они подгружаются во фрейм, этому всячески сопротивляются, они проверяют: либо это окно верхнего уровня, либо нет, и в окна не верхнего уровня не загружаются. Например, Google выдает какую-то табличку, Твиттер, загружаясь во фрейм, пытается найти parent-окно и туда загрузиться. Я хочу этому противодействовать.
  • Хочу иметь полноэкранный режим как в игрушках, из которого не так просто выйти, т.е. полноэкранный режим, в котором приложение запускается и в нем же работает. Не браузерный FullScreen.
  • Хочу распространять, рекламировать свое приложение через маркеты. Сейчас очень много маркетов, очень модно туда свое приложение загружать, там есть маркетинговые ходы, чтобы раскручиваться.
  • И просто, но очень важно — я хочу, чтобы мое приложение запускалось по клике на иконочку. Я не хочу набирать url или заставлять пользователя набирать этот url. Я хочу дать ему это приложение, он его установит, нажмет на иконку, и оно запустится.

Возможно ли все это сделать в приложениях написанных на веб-технологиях с помощью nw.js? Да, это возможно. И это возможно сделать очень легко. До nw.js, о котором я буду рассказывать (он совсем недавно так вылез на поверхность и стал таким популярным), какие еще есть решения?

Есть Adobe Flash (http://www.adobe.com/products/flash.html), Chrome apps https://www.google.com/chrome/webstore/apps-games.html), Tide SDK (ex. Titanium Desktop — http://www.tidesdk.org/), App.js (http://appjs.com/), Brackets Shell (https://github.com/adobe/brackets-shell), Tint (https://www.trueinteractions.com/tint2/docs) и др.

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



С nw.js (http://nwjs.io/) все намного проще. Если вы когда-либо писали веб-приложение, а еще экспериментировали или работали с Node.js, то вы уже часа через два будете иметь возможность написать десктопное приложение под три платформы, которое будет работать.

По моему субъективному мнению, на рынке есть два достойных решения для этого. Это nw.js, о котором мы будем говорить, и Electron (http://electron.atom.io/).



Это, на самом деле, последователь nw.js, он разрабатывается разработчиками Github, которые делают Atom, IDE Atom написано на Electron. Он раньше назывался Atom Shell, и буквально в апреле они его переименовали в Electron.

Мы сегодня будем делать выбор «по звездам», т.е. я зашел на Github, посмотрел у кого из них больше звезд, больше комьюнити, и вы брал для себя одно из них. На самом деле, Electron подает очень большие надежды, поэтому, может быть, через год стоит задуматься, чтобы переключиться на Electron. Надо смотреть, как он будет развиваться. В любом случае у них совсем не много принципиальных различий. Поэтому переключиться через год с nw.js на Electron будет не так сложно. И я в конце расскажу принципиальное отличие между ними.

nw.js проект раньше назывался node-webkit, у него есть история.



В 2011 году у Roger’а Wang’а — разработчика из Китая — появилась идея скрестить Node и webkit, сделать веб-приложение. Назвал он его node-webkit, потому что webkit тогда был рендер-движком Chromium’а, сейчас это Blink. Шли годы, проект развивался, все было хорошо, но к теперешнему моменту он потерял свое название.

В апреле 2013-го Chromium переехал на Blink (http://blog.chromium.org/2013/04/blink-rendering-engine-for-chromium.html, т.е. webkit потерялся, а с января 2015-го проект начал использовать io.js https://groups.google.com/forum/#!msg/nwjs-general/V1FhvfaFIzQ/720xKVd0jNkJ). Тут уже Node.js потерялся. Хотя Node.js, возможно, скоро вернется, судя по новостям. Поэтому проект переименовали в nw.js и заложили в эту nw такой сакральный смысл — native web. Поддерживается он Intel и gnor.net.

Основная идея.

У нас есть десктопные приложения. Чем они принципиально отличаются от веб-приложений? Тем, что та машина, которая отрисовывает интерфейс, на ней же в основном происходят и изменения. Т.е. файловый менеджер, который отрисовывает интерфейс, позволяет менять файлы на машине, на которой запущено это приложение. В веб-приложениях, в основном, все организованно по-другому: есть браузер, который что-то отрисовывает, а все изменяется на сервере, который где-то далеко. Поэтому в nw.js разработчики захотели приблизить веб-приложения к десктопным приложениям. Как они это сделали?



У nw.js есть две составные части — это Chromium и io js.

Что такое Chromium? Это браузер с открытым исходным кодом, который очень похож на Chrome, поддерживается он Google, Opera software, Яндексом, Nvidia — большими такими дядьками. У него в основе лежит Blink как движок для рендеринга, движок для javascript — это V8.

Node.js, написанная на С++, работает на уровне протоколов прикладного уровня, у нее есть доступ к каким-то сетевым взаимодействиям, файловой системе и прочим системным фишкам. Т.е. она из-за этого больше используется на серверах и для автоматизации какой-то.

Оба они используют V8. Один и тот же V8. Знаете откуда такое название?



Когда разработчики создавали V8, они взяли за основу такую идею движка… V8 — потому что клапана расположены буквой V и их 8 (клапанов). Двигатель V8 уже давным-давно используется.

В 1902 году, эта штука называлась арианет, по-моему, и в ней уже использовался V8:



А это Chevrolet Camaro 2015 года и в ней тоже используется V8.



Если браузерный V8проживет такую же жизнь, то будет очень классно.

Вернемся к V8. Основная идея — это объединить два этих мира и сделать их рабочими на одном и том же движке в одном и том же контексте. Т.е. вы можете из дома вызывать непосредственно функции Node.js, подключать модули Node.js, передавать объекты по ссылке, работать в едином контексте, иметь один event loop. Если точнее сказать, то здесь Node.js работает на движке V8, который есть у Chromium’а.

Давайте приведу небольшой пример.



У нас есть fs в Node.js для работы с файловой системой. Мы можем смотреть за изменениями в каком-то лог-файле, и если они произошли, то мы берем DOM элемент и отрисовываем в него содержимое этого лог-файла. Просто на сервере это невозможно, на клиенте это тоже невозможно, нет доступа к файловой системе юзера. А в декстопном приложении nw.js все это будет работать отлично.

Как они это сделали?

Было две основных проблемы: это сделать все в одном рабочем event loop, и чтоб оно работало в едином контексте. Т.е. нет какого-то window и global, есть глобальный контекст, в котором есть и Node.js и браузерный javascript. Здесь можно почитать подробнее — https://github.com/nwjs/nw.js/wiki/How-node.js-is-integrated-with-chromium.

Начинаем погружение. Как начать работать с nw.js? Вы заходите на nwjs.io, скачиваете оттуда файл для своей платформы для билдов, и дальше ваше приложение вы можете строить по какому угодно принципу.



Никто вам не говорит, куда класть html, куда — css, вы просто располагаете приложение так, как хотите, полностью всю структуру. Единственное, что вы должны иметь, это package.json. Это файл абсолютно такой же, как в любом Node.js приложении, но у него будут еще несколько дополнительных полей.



Это main — с какого файла начать работу.

Много установок для параметров окна, dependencies, которые нужны для нода.

Потом можно еще передавать туда флаги, с которыми запускается Chromium, флаги, с которыми запускается Node, и еще какие-то системные настройки, коих хватает.



Далее, мы в нашем тестовом случае напишем такое приложение. У нас будет div, у которого есть какой-то контент, добавим немного CSS, и все, что нам нужно запустить, — это nw app. Где nw app — это путь к директории с вашим приложением. При этом на экране вы увидите что-то такое:



Т.е. запустится приложение, появится иконочка. Это очень похоже на браузер. На самом деле, это и есть браузер, это просто обычный Chromium.

Но тут сразу хочется сделать его менее похожим на браузер, потому что это все-таки десктопное приложение, а тут еще много всего там сверху.

Для этого есть множество настроек, коротко пробежимся по некоторым из них. Можно убрать toolbar, это в конфиге.



Будет выглядеть как-то так:



Можем дальше убрать фрейм, т.е. ту штуку с кнопочками.



Будет как-то так:



Уже более похоже на что-то такое декстопное.

Дальше можем сделать это вообще все transparent, т.е. прозрачным:



При этом, у нас будет просто текст в висеть над нашим рабочим столом — никаких признаков браузера:



Можно запустить приложение в kiosk mod’е.



Kiosk mod используется для игрушек, в основном. Еще хорошо используется для всяких терминалов, инфо-киосков, больших всяких панелей, которые отображают меню в Макдональдсе и т.п. Он полноэкранный, из него выйти очень тяжело, из него выходят только описанными методами, либо alt+tab, либо ctrl+alt+del в винде. Поэтому, если вам нужно в kiosk mod’е, выглядит это все вот так, т.е. полностью занимает ваш экран:



Это не FullScreen, никаких панелек не будет выезжать, если вы будете куда-то подводить мышку. Для него нужно будет предусмотреть кнопочки для того, чтобы дать пользователю выйти из всей этой красоты. Иначе пользователь должен будет убить его в процессах.

Либо вы можете вообще запускать приложение в фоне, вообще без окна, будет вот так:



Что еще есть из красивых всяких плюшек?



Nw.js в стандартном пакете дает вам API для управления какими-то системными элементами интерфейса. Это можно создавать всякие менюшки, иконки в трее, notifications, можно работать с буфером обмена, с системными сочетаниями клавиш, т.е. не браузерными, когда у вас приложение в фокусе, и если вы что-то нажали, у вас что-то произойдет, а сочетаниями клавиш на уровне системы. Т.е. у вас приложения не видно, вы что-то нажали, оно появилось, либо что-то сделало — скриншот или еще что-то. Все это подключается через require nw.gui. Эта штука идет в стандартные поставки, ее подключать ниоткуда не надо.

Коротко пробежимся по ним. Контекстные менюшки.



Создаются очень просто: пишете такой Javascript — нам нужно меню, нам нужны несколько пунктов этого меню, нам нужен один сепаратор, т.е. разделитель между пунктами, и на один из пунктов меню, мы повесим «привет». Получится штука, которую мы повесим на правую кнопочку, и у нас будет такая системная менюшка:



Т.е. она на маке будет выглядеть вот так, на винде она будет выглядеть абсолютно по-виндовому, на убунте или другом линуксе, абсолютно по-линуксовому.

Оконное меню.



Такая же история. Создаем такую же менюшку, только даем ей роль менюбара. Получаем такую менюшку с вложенными пунктами меню:



Трей или менюбар, в других ОС.



Тоже создаем иконку в трее, можем вешать на нее какие-то выпадающие менюшки, есть иконочка, название, тут какие-то чекбоксики, выпадающие списочки, т.е. все это тоже можно сделать.



Причем, все эти евенты, которые там будут вызываться, будут доходить до вашего браузерного окна, и там можете что-то делать, или в ноде, или в DOM'е, не важно.

Сочетания клавиш.



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

Буфер обмена. Clipboard.



Такая же история. Пока они поддерживают только текстовый клипборд, обещают с разметкой в будущем тоже поддерживать, но пока вы можете положить что-то в буфер обмена и получить что-то из буфера обмена. Т.е. можно уже придумать себе какое-то приложение, где вы нажимаете какое-то сочетание клавиш, и ваш буфер обмена отправляется куда-то в облако, или еще что-нибудь. Здесь главный принцип — не навредить. Потому что nw.js снимает очень много ограничений по безопасности. Вы можете удалять юзерские файлы, вы можете их отсылать куда угодно, вы можете портить все подряд. На самом деле это круто. Свобода — это круто, а не то, что можно все портить.

Хранение данных.

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



Для хранения этих статических файлов nw.js дате вам такую переменную App.dataPath (https://github.com/nwjs/nw.js/wiki/App), это директория, она будет на каждой ОС разная, но если вы будете использовать именно эту директорию для хранения вашего статичного контента, то вы можете быть спокойны, он там будет хорошо храниться, будет все хорошо. Оно состоит из имени вашего приложения, так что никакого конфликта между приложениями в этой папке не будет.

Для хранения структурированных данных, вы можете использовать все, что уже было создано в Chromium’е (у вас под руками последний Chromium), поэтому Web SQL Database, IndexedDB, Web Storage, Local Storage, Session Storage, Application Cache, все что угодно. Могу только посоветовать: в чистом виде их использовать не очень приятно, поэтому в nw.js были написаны тонны плагинов, я в статье у себя упомянул ссылочку на то, где эти все плагины есть.

Отладка. С отладкой все тоже очень хорошо. Есть такой путь — у вас в тулбаре есть такая шестереночка:



Открывается дебаггер, абсолютно такой же как в Chrom’е последнем. Вы там все дебажите. Ничем не отличается от Chrom’а. Если вы хотите еще больше свободы, вы можете еще запустить nw.js remote debugging port 1234, допустим, и у вас тот же хромовский дебаггер откроется по такому адресу.

Есть возможность Livereload (https://github.com/nwjs/nw.js/wiki/Livereload-nw.js-on-changes), т.е. когда вы меняете код, ваше приложение автоматически обновляется. Они там ничего нового не придумали, они используют плагины, вотчи, которые просто перезагружают это окошко.

Со сборкой приложений (https://github.com/nwjs/nw.js/wiki/How-to-package-and-distribute-your-apps ). Если вы впервые столкнетесь с nw.js, пожалуйста, не старайтесь делать это все вручную. Потому что документация посоветует вам что-то вот такое:



Это страничка документации, и когда ее читаешь, там много всяких dll, каких-то линуксовых заморочек, еще чего-то. Первое ощущение, что все, на этом я закончил работать с nw.js. Но на самом деле, есть прекрасный плагин, называется он node-webkit-builder (https://github.com/mllrsohn/node-webkit-builder):



Там уже вся эта штука описана, автоматизирована и работает. Все, что вам нужно сделать, это скачать его, запустить команду nwbuild с путем к вашему приложению, и можете еще задать много флажков разных, допустим, под какие ОС билдить. При этом он полезет, выкачает последнюю сборку для всех ОС, загрузит себе, все сбилдит, разложит вам по папочкам. Т.е. у вас будет линукс 64, линукс 32, виндовс 64, видновс 32 и т.д. Все эти папочки уже с готовыми файликами для исполнения. Все, что вам остается, это их открыть либо под виндой, либо под линуксом, либо под маком.

Что у меня получилось? После запуска этой команды, так приложение выглядит на маке:



Так на винде:



Правда, шрифта робота в винде нет, поэтому шрифт поехал, но я его просто не подключил.

И так выглядит под убунтой:



Т.е. менюшки выглядят так же, как любые убунтовские менюшки.

Хочется сравить nw.js и Electron. Потому что Electron все больше набирает обороты. На самом деле, nw.js и Electron отличаются совсем немножко.



Есть такая история, которую рассказывал Роджер Ванг в одном из докладов, то, что когда он разрабатывал node-webkit на одной из стадий им заинтересовались разработчики Github. И начали какие-то вопросы задавать: что, как, почему? И какие-то у них были идеи по совместному использованию этого всего. И с ним работал его интерн, т.е. рядом чувак, который тоже что-то там пишет, помогает. Вот и через какое-то время этого наняли в Github, который начал писать Electron. Потом они сделали Atom Shell, потом Atom, потом Electron. Поэтому концептуальных различий между ними очень мало. Различия есть, но для конечного разработчика они очень небольшие.

Первое — это точка входа, т.е. в nw.js, мы сразу открываем какой-то файлик index.html и показываем его в окошке. В Electron вы работаете больше с Javascript, т.е. вы сразу не показываете никакого html. Вы в Javascript создаете это окошко, и потом его показываете. Это, наверное, все различия. В Electron у них разные принципы построения билдов, что в принципе нас не волнует, потому что я все равно не хочу читать всю ту документацию. Измененный против оригинального Chromium’а, т.е. ребята в Electron, который бывший Atom Shell, не захотели изменять Chromium, они как-то там выкручиваются, чтобы, вообще, никак не патчить Chromium и использовать тот, который есть. В nw.js они его пропатчивают и убирают какие-то настройки безопасности и еще что-то.

И еще одно различие — в контексте. В nw.js контекст общий, если вы насоздаете много окошек, то в Electron он разный. В принципе, для простых приложений, это не особо важно. Подробнее с точки зрения разработчиков Electron, чем они отличаются от nw.js (там, конечно, уклон в сторону Electron), можно почитать здесь — https://github.com/atom/electron/blob/master/docs/development/atom-shell-vs-node-webkit.md.

И несколько хороших примеров. Примеры — это не самые успешные продакшн приложения, но это просто приложения, разные по своей сути. Может, вас натолкнет на какие-то мысли, идеи, что бы разработать.



Первое — это Popcorn Time. Приложение, которое позволяет стримить из торрентов кино и сериалы.

В отличие от таких подобного рода приложений, оно абсолютно user friendly, оно нигде вам не говорит с какого торрента и как оно все это стримит, вы заходите, там много сериалов, вы выбираете один из них и смотрите. Написан на nw.js, работает под маком, виндовс и линукс.

Есть приложения больше системные. Эта штука такая mongo management studio, очень напоминает php my admin толmко для mongo. Еу, такое gui для mongo.



Есть Light table — редактор, очень похож на Sublime или Atom. Они утверждают, что он намного круче, потому что у него какая-то определенная философия. Я ее не постиг, но есть адепты…



Есть вот такие штуки — вы можете почувствовать себя в роли радиоведущего, стримить свое аудио в массы:



Есть очень похожие клоны десктопных приложений, например, показывающие весь ваш диск вот так вот размеченный:



Вы можете посмотреть, где лежат большие файлики и их поудалять.



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

И вот, единственное, что я нашел на русском языке на nw.js, эта штука для быстрой сдачи налогов:



Я думал, что в России налоги никто не сдает, оказывается, для этого даже софт предусмотрен. И штуку эту начали разрабатывать в 2013 году, она была предназначена для телефонов отдельно, для десктопов отдельно и отдельно для терминалов и инфо-киосков. Эта версия для терминалов, т.е. в терминалах вы тоже можете увидеть приложения, разработанные на nw.js. Но все-таки я был прав, что налоги в России никто не сдает, поэтому она так и загнулась в 2013 году и дальше у нее никакой судьбы не было.

Еще очень много приложений они у себя в репозитории ( https://github.com/nwjs/nw.js/wiki/List-of-apps-and-companies-using-nw.js ) собирают. Если вы что-то хорошее напишете, дополнительный какой-то маркетинг, может, от этого вам будет, вы можете тоже там у них в репозитории разместить, и ваше приложение будет в этом большом списке. Список очень большой, там около 100 приложений.

Хотелось бы сделать какие-то выводы. Стоит ли писать приложения на веб-технологиях под десктоп?



Что мне кажется, субъективно, но хочу поделиться.

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

Работает достаточно быстро. Конечно, можно сказать, что приложения будут работать быстрее, которые написаны на IT-технологиях, но если взять соотношения скорости работы к деньгам и ресурсам, затраченным на разработку, то, возможно, nw.js будет намного далеко впереди.

Нарастающий тренд — все и всё пишут на вебе везде, для квадрокоптеров, телевизоров, холодильников и, в том числе, для десктопа сейчас, почему бы нет? Просто писать приложения для себя. Т.е. написать такое приложение, допустим, у вас есть какой-то скрпит, который чего-то там билдит, потом тестирует, и потом выкладывает на продакшн или на стейджинг. И вы хотите сделать это вручную, не какими-то тулзами, а вручную. Обычно вы запускаете в консольке какие-то команды. Но вы хотите, чтобы это мог делать, допустим, тестировщик, или вы хотите, чтобы это мог делать верстальщик, который не хочет вообще видеть вашу консоль. И для этого можете написать простенькое десктопное приложение с тремя кнопочками (это займет минут 20), которое будет в командной оболочке запускать нужные команды, при нажатии на эти кнопочки.

Пишите приложения для себя. И это дешево во всех отношениях. Это дешево в обучении разработчиков, потому что их не надо обучать, им нужно дать посмотреть слайды и все. Дальше это дешево с точки зрения, что вам нужны просто веб-разработчики, вам не нужны какие-то узкопрофильные разработчики, которые вам будут писать приложения под линукс или под мак.

Если остались вопросы, то смотрите еще:

Контакты


» Блог http://html5.by/
» Твиттер @html5by и @nedudi
» Группа ВК http://vk.com/html5by
» Группа FB http://facebook.com/html5by

Этот доклад — расшифровка одного из лучших выступлений на конференции фронтенд-разработчиков FrontendConf.

Ну и главная новость — мы начали подготовку весеннего фестиваля "Российские интернет-технологии", в который входит восемь конференций, включая FrontendConf.
Tags:
Hubs:
+36
Comments119

Articles

Information

Website
www.ontico.ru
Registered
Founded
Employees
11–30 employees
Location
Россия