Как я уже писал, конкуренция среди облачных платформ привела к тому, что для для невысоких по нагрузке задач ими можно пользоваться абсолютно бесплатно. При этом каждая из платформ старается продвигать уникальные «фишки» и балансирует платные и бесплатные предложения, которые варьируются в очень широких пределах от многолетнего «Bizspark» у Azure до «засыпающих» на 8 часов в сутки инстансов Heroku. Недавно купленная facebook платформа «parse.com» предлагает собственный ORM, россыпь SDK для всех платформ и довольно интересный облачный хостинг «parse cloud code», позволяющий использовать в их облаке javascript не только для работы с данными, но и для создания средней сложности сайтов. Модель монетизации у них тоже любопытная: сервисом можно пользоваться бесплатно, пока количество запросов к одному приложению не превышает 30 в секунду. А это, между прочим, довольно много. Под катом я расскажу как в несколько строк кода сделать заготовку веб сервиса, используя самый актуальный стек технологий: typescript 1.6 с jsx, React 0.13 с es6, webpack с лоадерами в ассортименте и немного свежего express.js

Зачем еще одна платформа


Как уже знают многие читатели, я старательно и планомерно продвигаю на Хабре нашу платформу облачной телефонии voximplant, которая полностью управляема с помощью javascript и дружественна к веб разработчикам. К нам часто обращаются клиенты и партнеры, которые хотят из javascript во время звонков сохранять и читать данные: собирать статистику, рисовать dashboard, делать синхронизацию по внешним событиям и так далее. Мы им честно рассказываем что из нашего облака можно делать http запросы к любым сервисам, с помощью которых можно реализовать все что они хотят. И сталкиваемся с непониманием — «ну это же сервак поднимать надо… это сложно… долго… дорого». В этой статье я продемонстрирую насколько быстро сейчас можно собрать бесплатное fullstack решение, способное обрабатывать http запросы, хранить данные и быстро показывать их изменение. Ну а чтобы статья была интересна максимальному кругу хабражителей, сервис выбран необычный, а стек технологий — самый, не побоюсь этого слова, трендовый. Кстати, в комментариях приветствуются обсуждения js vs python vs ruby, react vs angular vs ember и webpack vs browserify vs grunt vs gulp.

Подготавливаем toolchain


Устанавливаем последнюю версию node.js, регистрируемся на parse и устанавливаем себе их одноименную command line tool по инструкции. Установленный toolchain даст нам волшебную команду parse, с помощью которой можно не только создать новый проект, но и загрузить его в облако, и посмотреть логи. В общем, все как у всех.



Создаем приложение


Приложение создается командой parse new, которая позволит создать новое приложение или подключиться к существующему, и в случае создания нового приложения — создаст минимальный «скелет» в указанной директории. Созданное приложение можно сразу же загрузить в облако, выполнив в его директории команду parse deploy. Отгруженное в облако приложение будет доступно по url, которое нужно задать в настройках веб интерфейса, раздел «hosting»:



Созданный скелет приложения состоит из двух файлов: cloud/main.js для javascript кода и public/index.html для статики. Если мы зайдем на заданный нами url, то увидим как раз содержимое статичного html файла:



Добавляем немного express.js


Статика нам не очень интересна, поэтому запускаем команду parse generate, которая добавляет в наше приложение скелет express.js. Тут надо уточнить: в отличие от большинства других paas сервисов, parse.com это не node + git. Их облачная инфраструктура строится вокруг «голого» движка V8, в который они добавили модули стандарта common js и немного api. В их облако нельзя установить модули node.js (хотя можно «склеить» их в один .js файл вместе с приложением), а команда parse deploy никак не связана с git и просто копирует в облако содержимое директорий cloud и public, снабжая каждую загрузку «версией». После загрузки в облако всегда выполняется файл cloud/main.js в котором можно инициализировать express.js и получить полноценное приложение. Но постойте, откуда в облаке express.js, если там нет ноды? Все очень просто — parse предоставляет ряд популярных библиотек, которые можно загрузить с помощью require и использовать для создания приложений и доступа к сервисам. С полным списком можно ознакомиться здесь — он не то чтобы очень большой, но самое нужное там есть.

Если сейчас запустить модифицированное приложение, то мы снова увидим содержимое index.html. Причина в том, что генератор добавил файлы экспресс, но не прописал их в «точке входа» main.js. Исправляем это упущение и меняем содержимое main.js на такой код:

require('cloud/app.js');

Обратите внимание, что при использовании поставляемых в комплекте библиотеки в require передается только имя библиотеки, а при загрузке ваших собственных файлов нужно прописывать путь от корня проекта. Такую реализацию require сделали ребята из parse, можно только догадываться зачем. В любом случае, загрузив новую версию приложения и перейдя по url /hello мы увидим работающий express.js

Переходим на typescript


Typescript от Microsoft добавляет в javascript возможность использовать строгую типизацию (или не использовать, это дело добровольное), синтаксис es6 и много других интересных штук. Кроме модулей. То есть синтаксис для модулей в языке присутствует, но скомпилированные .ts файлы породят такое же количество .js файлов, в которых код работы с модулями превратиться в набор вызовов api по выбранному стандарту: common js, amd итд. Можно, конечно, собрать отдельно common js версию для backend, amd для frontend, подключить загрузчик amd… Но есть вариант проще: использовать один из инструментов управления зависимостями, который склеит все получившиеся .js файлы в один, правильно «пропатчив» код работы с модулями.

В качестве такой системы я выбрал webpack — самое последнее решение, способное при удачном стечении обстоятельств не только организовать модули, но и заменить систему сборки, в роли которой обычно выступает grunt или gulp

Для установки компилятора typescript, webpack и ряда полезных утилит используем следующее заклинание node package manager (который обычно ставится вместе с node.js):

npm init
npm install typescript tsd webpack underscore ts-loader style-loader css-loader sass-loader node-sass --save

Чтобы typescript хорошо работал и проверял типы, нужно установить так называемые «type definitions» — описания типов для популярных библиотек, которые создаются и поддерживаются разработчиками. Делается это с помощью утилиты tsd, которую мы поставили вместе с компилятором:

tsd install express
tsd rebundle

Чтобы webpack собирал typescript, создадим для него конфигурационный файл webpack.config.js, единственный объемный кусок кода в моей демонстрации:

var _ = require('underscore');

var BASE_CFG = {
  resolve: {
    extensions: ['', '.js', '.ts', '.jsx', '.tsx'],
  },
  module: {
    loaders: [
      {test: /\.ts(x?)$/, loader: 'ts-loader'},
      {test: /\.scss$/, loaders: ['style', 'css', 'sass']},
    ],
  },
};

var BACKEND_CFG = _.extend({}, BASE_CFG, {
  target: 'node',
  entry: './src/backend.ts',
  output: {
    path: './cloud',
    filename: 'main.js',
  },
  externals: {
    'express': 'commonjs express',
  },
});

module.exports = [BACKEND_CFG];

Теперь можно стереть все из папок public и cloud, заменив на единственный файл с кратким кодом бэкенда, src/backend.ts:

/// <reference path="../typings/tsd.d.ts" />
import * as express from 'express';
const app = express();
app.get('/', (req, res) => res.end("hello, habr!"));
app.listen(8080);

Краткость — сестра. Собираем и отгружаем в облако:

webpack
parse deploy

Добавляем ReactJS


ReactJS, детище Facebook, было создано с амбициозной целью починить чатик. И как-то неожиданно обрело мировую известность. Основной «фичей» стал не рекламируемый shadow dom с быстрыми обновлениями, а возможность раздробить интерфейс и часть логики веб приложения на небольшие, простые и хорошо изолированные кусочки. Добавляем в наш проект саму библиотеку, не забывая о type definitions для typescript:

npm install react --save
tsd install react --save

Добавим в конфигурацию webpack правила для сборки frontend части:

var FRONTEND_CFG = _.extend({}, BASE_CFG, {
  target: 'web',
  entry: './src/frontend.tsx',
  output: {
    path: './public',
    filename: 'frontend.js',
  },
  ts: {
    compilerOptions: {
      'jsx': 'react',
    },
  },
});

module.exports = [FRONTEND_CFG, BACKEND_CFG];

И собственно сам код frontend в файле src/frontend.tsx, который так же будет написан на typescript (обратите внимание на расширение, гремучая смесь typescript и xml):

/// <reference path="../typings/tsd.d.ts" />
import * as React from 'react';

class Ui extends React.Component<any, any> {
  render() {
    return <div>helo, habr</div>;
  }
}

document.addEventListener('DOMContentLoaded', () => {
  React.render(React.createElement(Ui), document.body);
});

Чтобы React загрузился на фронтенде, немного модифицируем src/backend.ts:

app.get('/', (req, res) => {
  res.end('<script type="text/javascript" src="frontend.js"></script>');
});

Все готово — собираем, загружаем в облако и видим заготовку пользовательского интерфейса на ReactJS. Которую можно очень быстро превратить в полноценный интерфейс с помощью готовых наборов компонентов

Добавляем SASS


Webpack — это не только конкурент Browserify, нехорошо поглядывающий на gulp. Это еще и возможность подключать через require файлы, отличные от javascript. Например — css стили. Или sass, что сейчас более популярно. У такого подхода есть плюсы и минусы, при этом плюсы лежат в области лучшей читаемости и организации кода, а минусы — в скорости загрузки того что получилось. Каждый выбирает под свои задачи, главное — чтобы было легко использовать. А с webpack подключение sass стилей становится вопросом одной строчки кода. Вот такой:

require("./frontend.scss");

Благодаря настойкам в конфигурационном файле webpack, указанный .scss файл будет преобразован в css, добавлен в виде текстовой строки в результирующий javascript и автоматически загружен в dom на клиенте. При необходимости процесс можно тонко подстроить под свои нужды и оптимизировать по скорости загрузки, но простейший случай решается ровно в одну строчку кода, что не может не радовать. Загруженные стили можно использовать в ReactJS в соответствии с синтаксисом JSX:

render() {
  return <div className='ui'>styled hello, habr</div>
}

Заключение


Основная сила Parse лежит в ORM: возможность создавать объекты «на лету», складировать их в емкую базу данных и получать обратно простым javascript кодом позволяет создавать прототипы веб приложений с очень высокой скоростью. Я не стал добавлять в статью еще и пример работы с данными, чтобы не получить очередной wall of text, но документация на официальном сайте позволяет быстро войти в курс дела. А если добавить к этому ReactJS с готовыми компонентами для пользовательского интерфейса, встроенный в Parse механизм работы с пользователями и удобный набор «батареек», то получившийся комбайн в умелых руках способен на многое. Плюс к этому — бесплатный тарифный план, в который умещается очень много не только небольших, но и средних проектов. 30 запросов в секунду это много. И это я не говорю про мобильные SDK, React Native и встроенную в dashboard систему аналитики. Есть на что посмотреть.

К минусам следует отнести общую слабость хостинговой платформы: по моим ощущениям, все создавалось вокруг ORM, и возможности делать веб приложения и выполнять произвольный код в облаке были добавлены значительно позже. Голый V8 вместо node.js, невозможность установить большинство модулей и еще ряд ограничений не позволяют рассматривать parse как совсем универсальное решение. Но, тем не менее, для многих задач платформа подходит очень хорошо — что, я надеюсь, и было продемонстрировано в статье. Вопросы, уточнения, немного флейма в понедельник?

Комментарии (8)


  1. RUQ
    05.10.2015 09:54
    +1

    Стоит сказать, что основной для javascript'ового API Parse служит Backbone. Но если хотите использовать его на 100%, то всё же необходимо подключить его отдельно (backbone). А в целом Parse очень крутое подспорье frontend-специалисту, помогает на ранних стадиях приложения обходится вообще без backend-части, соответственно экономятся силы и время.

    В Parse есть всё для построения стандартных CRUD систем, кроме того есть api для работы с гео-объектами, файлами, упрощённая регистрация пользователей + facebook login.


    1. eyeofhell
      05.10.2015 10:04
      +2

      Плюсую, backbone там есть. Правда, не в чистом виде, а в виде форка, на котором построен их SDK для работы с ORM. Сделать require('backbone') в cloud code нельзя :)


      1. kurtov
        05.10.2015 18:38
        +2

        В недавней версии 1.6 решили отказаться от использование Backbone и развиваться своим путем.

        «SDK no longer contains Backbone-specific behavior. Moving forward, the core SDK will not be tied to any single framework, but we will work with the community to produce up-to-date bindings like Parse+React. The major changes are the removal of Parse.Collection, and allowing Parse.Objects to act as event channels.»


  1. Anisotropic
    05.10.2015 11:32

    >react vs angular vs amber
    Amber.js переименовали в Ember.js 4 года назад :)


    1. eyeofhell
      05.10.2015 12:10
      +1

      Точно, это уже не первый раз когда я так опечатываюсь -_-. Хорошо хоть Qt пока правильно пишу :).


  1. aylarov
    05.10.2015 13:39
    +1

    TypeScript + React + Webpack отличное сочетание, еще бы в Sublime нормально работал плагин для TypeScript (подгружал type definitions без проблем)…


    1. forcewake
      05.10.2015 18:44
      +1

      Можете попробовать Atom с пакетом atom-typescript. Даже сейчас вполне юзабельно и вполне себе удобно использовать.


      1. aylarov
        05.10.2015 20:54
        +1

        Уже вроде победил Sublime, но буду иметь в виду