# ES2015, React HMR

*ОБНОВЛЕНИЕ 2018: Вышло* [*второе издание*](https://maxfarseer.gitbooks.io/redux-course-ru-v2/content/) *(современный код и версии пакетов, данное издание УСТАРЕЛО)*

*На* [*канале*](http://bit.ly/2IqH74P) *так же проводятся бесплатные вебинары, публикуются переводы и авторские материалы,* [*присоединяйтесь*](http://bit.ly/2IqH74P)*!*

## ES2015, React HMR

Для использования возможностей ES6(2015) и ES7 будем использовать babel. С выходом 6й версии, он стал очень модульным, поэтому не пугайтесь большому количеству зависимостей.

### Babel 6

Все начинается с

```
npm install babel-core babel-loader --save-dev
```

Далее нужно поставить пресеты (*предустановки*), которые нам нужны.

```
# Для поддержки ES6/ES2015
npm install babel-preset-es2015 --save-dev

# Для поддержки JSX
npm install babel-preset-react --save-dev

# Для поддержки ES7
npm install babel-preset-stage-0 --save-dev
```

Нам однозначно нужен полифил, чтобы все фичи работали в браузере

```
npm install babel-polyfill --save
```

И немного улучшим время сборки, добавив следующие пакеты

```
npm install babel-runtime --save
npm install babel-plugin-transform-runtime --save-dev
```

\*Для написания этого небольшого текста про babel 6, я использовал статью [Using ES6 and ES7 in the Browser, with Babel 6 and Webpack](http://jamesknelson.com/using-es6-in-the-browser-with-babel-6-and-webpack/)\*

В данный момент, у нас достаточно "пакетов", чтобы писать "современный" код и использовать JSX. Давайте в этом убедимся.

Во-первых, подправим конфиг для webpack'а:

*webpack.config.js*

```javascript
var path = require('path')
var webpack = require('webpack')

module.exports = {
  devtool: 'cheap-module-eval-source-map',
  entry: [
    'webpack-hot-middleware/client',
    'babel-polyfill',
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],
  module: { //Обновлено
    loaders: [ //добавили babel-loader
      {
        loaders: ['babel-loader'],
        include: [
          path.resolve(__dirname, "src"),
        ],
        test: /\.js$/,
        plugins: ['transform-runtime'],
      }
    ]
  }
}
```

Добавилась запись в секции loaders. Теперь все js файлы в *src* директории будут обрабатываться *babel-loader*'ом, которому мы в свою очередь тоже должны указать настройки. Для этого, нужно создать файл .babelrc со следующим содержимым:

```javascript
{
  "presets": ["es2015", "stage-0", "react"] //поддержка ES2015, ES7 и JSX
}
```

Если вы знакомы с *gulp*, то можно провести некую аналогию, между плагинами gulp и лоадерами (loaders) webpack'a. Если мы хотим делать какие-то преобразования с кодом внутри файла, будь то css, js или картинки - мы используем соответсвующий *loader*. Причем создавать дополнительные файлы настроек, как в случае с babel, обычно не нужно.

Ок, создадим React компонент, не забыв при этом скачать нужные пакеты:

```
npm i react react-dom --save
```

*src/index.js*

```javascript
import 'babel-polyfill'
import React from 'react'
import { render } from 'react-dom'
import App from './containers/App'


render(
  <App />,
  document.getElementById('root')
)
```

*src/containers/App.js*

```javascript
import React, { Component, PropTypes } from 'react'

export default class App extends Component {
  render() {
    return <div>Привет из App</div>
  }
}
```

Перезапускаем сборку (`npm start`).

Весь код на текущий момент выложен в [специальную ветку на Github](https://github.com/maxfarseer/redux-ru-tutorial/tree/config_babel-6_with_React). Можете сверится, если что-то не работает.

### React + Hot Reload

Возможно, вам встретится аббревиатура HMR ([hot module replacement](https://webpack.github.io/docs/hot-module-replacement.html)), что в принципе более правильно отражает суть, поэтому под hot-reload я подразумеваю именно HMR ;)

Как вы помните из прошлой главы - мы добавили `module.hot.accept()`, для того, чтобы webpack обновлял код из файла *index.js* в сборке без перезагрузки страницы в браузере. Если сейчас попробовать изменить что-то в App.js - то в результате ничего не случится, ровно по тем же причинам, что и в предыдушем случае. Что ж, это поправимо и благодаря добрым людям, нам не нужно самим вписывать *accept* функцию. Итак, встречайте (и устанавливайте):

```
npm install react-hot-loader --save-dev
```

Достаточно добавить еще один loader в конфиг и мы получим hot-reload для React компонентов.

```javascript
var path = require('path')
var webpack = require('webpack')

module.exports = {
  devtool: 'cheap-module-eval-source-map',
  entry: [
    'webpack-hot-middleware/client',
    'babel-polyfill',
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],
  module: {
    loaders: [
      {
        loaders: ['react-hot', 'babel-loader'], //добавили loader 'react-hot'
        include: [
          path.resolve(__dirname, "src"),
        ],
        test: /\.js$/,
        plugins: ['transform-runtime'],
      }
    ]
  }
}
```

Перезапускаем сборку и проверяем. Теперь HMR работает и для React компонентов, если же нет - сверьтесь [с исходным кодом данного раздела](https://github.com/maxfarseer/redux-ru-tutorial/tree/configure_babel6_react_hmr).

Для того, чтобы начать писать код redux-приложения, я основательно рекомендую настроить ESLint, чтобы быстро решать синтаксические ошибки и повысить производительность. Этим мы займемся на следующем шаге.

P.S. В официальном репозитории [React-hot-reloader](https://github.com/gaearon/react-hot-loader)'a говорится о том, что готовится к выходу [React Transform](https://github.com/gaearon/react-transform-boilerplate), который станет логическим продолжением текущих решений. (31.01.2015)

P.P.S. [Как говорит](https://github.com/gaearon/react-hot-boilerplate/commit/79c05c82875ae9f6133e337b06066049e209a675) создатель библиотеки react-hot-reload, нам больше не нужно использовать `webpack.NoErrorsPlugin`, который ранее выполнял следующее: если в сборке были ошибки, он не обновлял файл сборки. Поэтому просто удалите соответствующую строку из секции plugins внутри *webpack.config.js*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://max-frontend.gitbook.io/redux-course-ru/chapter1/es2015-_react_hmr.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
