Разработка с Flask, ReactJS, gulp.js, bower, Browserify. Часть 1.

main-logo
image-4292

Давайте посмотрим на небольшую, но мощную JavaScript UI библиотеку ReactJS в действии. Это приложение работает на Python 3 и фремворке Flask, на back-end. Так же мы будем использовать на front-end: gulp.js (для выполнения задач), bower(front-end менеджер пакетов), и Browserify(пакетирование зависимостей JavaScript).

ReactJS

Реагировать библиотека, а не фреймворк. В отличие от клиентских MVC фреймворков таких как: Backbone, Ember, и AngularJS, React не делает никаких предположений о вашей технологии стека, так что вы можете легко интегрировать его в новый или унаследованного кода. Это часто используется, чтобы управлять конкретных областей UI приложение, а не всем пользовательским интерфейсом.

React заботится только о пользовательском интерфейсе, который определяется иерархией модульных views компонентов. Если вы знакомы с Anmgular эти компоненты аналогичны директивам. Компоненты используют синтаксис XML, именуемый JSX, который собирает в JavaScript.

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

Настройка проекта

Давайте начнем с того, что мы знаем: Flask.

Скачать шаблонный кода из репозитория, извлеките файлы, создавайте и активируйте virtualenv, и установите необходимые модули: pip install -r requirements.txt

Теперь давайте запустим приложение:

 $ sh run.sh 

React — первый раунд

Давайте посмотрим на простой компонент.

Компонент: переход от статичного к React

Мы добавим этот скрипт JSX в наш hello.html. Остановитесь на минутку, чтобы проверить его.

<script type="text/jsx">
  /*** @jsx React.DOM */
  var realPython = React.createClass({
    render: function() {
      return (
<h2>Greetings, from Real Python!</h2>
)
    }
  });
  React.render(
    React.createElement(realPython, null),
    document.getElementById('content')
  );
</script>

Что происходит?

  1. Мы создаем компонент с помощью вызова createClass(), и дали ему имя realPython. React.createClass() принимает один аргумент, объект.
  2. Внутри этого объекта мы добавили функцию render, которая декларативно обновляет DOM во время вызова.
  3. Затем идет возвращение значения Greetings, from Real Python!, в JSX, который представляет актуальный HTML элемент, который будет добавлен к DOM.
  4. В конце, React.render() создает экземпляр компонента realPython и вводит элемент в DOM с ID селектором content.

Трансформация

Что дальше? Мы должны «трансформировать», или скомпилировать, JSX в JavaScript. Это делается очень просто. Обновляем hello.html:

<!DOCTYPE html>
<html>
  <head lang="en">
    <meta charset="UTF-8">
    <title>Flask React</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- styles -->
  </head>
  <body>
<div class="container">
<h1>Flask React</h1>
<div id="content"></div>
    </div>
    <!-- scripts -->
    <script src="http://cdnjs.cloudflare.com/ajax/libs/react/0.12.0/react.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/react/0.12.0/JSXTransformer.js"></script>
    <script type="text/jsx">
      /*** @jsx React.DOM */
      var helloWorld = React.createClass({
        render: function() {
          return (
<h2>Greetings, from Real Python!</h2>
)
        }
      });
      React.render(
        React.createElement(helloWorld, null),
        document.getElementById('content')
      );
    </script>
  </body>
</html>

Здесь мы добавили скрипты react.js и JSXTransformer.js. Последний из них используется для «преобразования» синтаксис JSX в обычный JavaScript в браузере.

Обратите внимание, мы не добавили JQuery, так как это не требуется для React.

Вот и все. Запустите сервер Flask и проверьте результат в браузере по адресу: http://localhost:5000/hello

flask-react-hello-world
image-4293

Bower

Вместо того чтобы вручную скачивать JavaScript файлы или подключать их с CDN, давайте использовать Bower для лучшего управлениями этими зависимостями. Bower это мощный менеджер пакетов для фронтальных зависимостей, таких как: JQuery, Bootstrap, React, Angular, Backbone.

Убедитесь, что у вас уже установлен Node и npm. Если его нет то установите его.

Инициализация

Установим Bower с помощью npm:

$ npm install -g bower

npm это менеджер пакетов используется для управления модулями Node. В отличие от PyPi/pip, npm по умолчанию устанавливает зависимости локально. Флаг -g используется для переопределения, чтобы установить Bower глобально.

bower.json

Bower использует файл bower.json для определения зависимостей проекта, который похож на файл requirements.txt. Выполните следующую команду, чтобы в интерактивном режиме создать этот файл:

$ bower init

Просто нажимайте enter что бы установить значения по умолчанию. После этого файл bower.json должен выглядеть примерно так:

{
"name": "ultimate-flask-front-end",
"version": "0.0.1",
"authors": [
"Michael Herman <michael@realpython.com>"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

npm

npm использует аналогичный bower.json файл, называется package.json, он определяет зависимости проекта. Вы также можете создать его в интерактивном режиме:

$ npm init

Так же установите значения по умолчанию:

{
"name": "ultimate-flask-front-end",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

Теперь, давайте добавим файл bower в npm зависимости:

$ npm install --save-dev bower

Конфигурация

Наряду с файлом bower.json, мы можем определить параметры конфигурации Bower в файле .bowerrc. Создадим такой файл в корне проекта. Структура проекта должна теперь выглядеть следующим образом:

├── .bowerrc
├── .gitignore
├── bower.json
├── package.json
├── project
│   ├── app.py
│   ├── static
│   │   ├── css
│   │   │   └── style.css
│   │   └── scripts
│   └── templates
│       ├── hello.html
│       └── index.html
├── requirements.txt
└── run.sh

По умолчанию Bower установит пакеты в каталоге «bower_components» в корне проекта. Мы должны изменить это, так как Flask необходимо что бы файлы лежали в static. Таким образом, добавьте следующий JSON код в файл .bowerrc, так что бы Bower автоматически устанавливал файл в нужную директорию:

{
"directory": "./project/static/bower_components"
}

Инициализация

Мы должны установить следующие пакеты для этого проекта:

  • Bootstrap
  • jQuery
  • React

Это можно сделать двумя способами:

  1. Запустите bower install --save для каждого из пакетов (флаг —save добавляет зависимость (название и версию) в файле bower.json.).
  2. Обновите файл bower.json добавив названию и версию пакета, а затем запустить bower install, чтобы установить все зависимости от файла.

Давайте воспользуемся вторым способом.

{
"name": "ultimate-flask-front-end",
"version": "0.0.1",
"authors": [
"Michael Herman <michael@realpython.com>"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"./project/static/bower_components",
"test",
"tests"
],
"dependencies": {
"bootstrap": "~3.3.2",
"jquery": "~2.1.3",
"react": "~0.12.2"
}
}

И запустим bower install

$ bower install
bower cached git://github.com/twbs/bootstrap.git#3.3.2
bower validate 3.3.2 against git://github.com/twbs/bootstrap.git#~3.3.2
bower cached git://github.com/jquery/jquery.git#2.1.3
bower validate 2.1.3 against git://github.com/jquery/jquery.git#~2.1.3
bower cached git://github.com/facebook/react-bower.git#0.12.2
bower validate 0.12.2 against git://github.com/facebook/react-bower.git#~0.12.2
bower install react#0.12.2
bower install jquery#2.1.3
bower install bootstrap#3.3.2

react#0.12.2 project/static/bower_components/react

jquery#2.1.3 project/static/bower_components/jquery

bootstrap#3.3.2 project/static/bower_components/bootstrap
└── jquery#2.1.3

Теперь вы можете проверить файлы в каталоге «project/static/bower_components».

Тест

Обновите hello.html:

<script src="{{ url_for('static', filename='bower_components/react/react.min.js') }}"></script>
<script src="{{ url_for('static', filename='bower_components/react/JSXTransformer.js') }}"></script>

Протестируйте приложение, чтобы убедиться, что оно все еще работает.