parse.com как бесплатный fullstack: react.js + express.js + typescript + webpack в несколько строк кода

85dad0584cdb4e6f8c28397a5115cf17.pngКак я уже писал, конкуренция среди облачных платформ привела к тому, что для для невысоких по нагрузке задач ими можно пользоваться абсолютно бесплатно. При этом каждая из платформ старается продвигать уникальные «фишки» и балансирует платные и бесплатные предложения, которые варьируются в очень широких пределах от многолетнего «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 amber и webpack vs browserify vs grunt vs gulp.

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

a452e34f41d547af85d4c29336654284.png

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

14c15859239c439f9f4db4855c531e92.png

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

126967dc607f4ea2aac96368a0fa7aba.png

7492f4f489fd4985a37b1d7ff68b782b.pngСтатика нам не очень интересна, поэтому запускаем команду 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

955dcc6d9fbf42949863f63dde3992b5.pngTypescript от 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

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

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

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

<source lang="js">
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. Которую можно очень быстро превратить в полноценный интерфейс с помощью готовых наборов компонентов

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>
}

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

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

© Habrahabr.ru