Это руководство научит вас создавать React среду и начать разработку с react, webpack и sass. В этом руководстве мы не будем использовать create-react-app cli, вместо этого мы создадим среду react dev с нуля.

Сначала мы установим webpack и произведем минимальную настройку. Затем мы создадим простой React компонент. После этого разберемся с Redux. Наконец, мы можем написать некоторые правила стиля для компонента приложения с SASS и настроить загрузчики веб-пакетов для SASS объединения.

Предварительно требования:

  • Установлен Node.js
  • Базовые знания JavaScript.
  • npm или пряжа

Webpack

Создайте каталог проекта и двигайтесь по нему.

mkdir react-setup
cd react-setup

Критский проект по пряжи:

yarn init -y

Или npm:

npm init -y

Установите библиотеки webpack и webpack-dev-server.

yarn add --dev webpack webpack-cli webpack-dev-server

Создайте каталог src и создайте в нем файл index.js. Поместите код в src/index.js файл.

const foo = () => console.warn('OK');
foo();

Создайте webpack.config.js file в корне проекта.

Концепции конфигурации Webpack

Файл конфигурации содержит четыре основных раздела:

  • Entry - точка входа модуля, который вы хотите связать.
  • Output - указывает веб-пакет, куда помещать обрабатываемые бандлы.
  • Modules - массив загрузчиков.
  • Plugins - массив плагинов, решающих другие задачи.

Вход

В webpack.config.js определите ключ входа в объект экспорта.

module.exports = {
  entry: './src/index.js'
};

Как видите, src/index.js файл, который вы создали ранее, является точкой входа в ваш модуль.

Выход

Определите выходной ключ в объекте конфигурации.

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve('./dist'),
    filename: 'bundle.js'
  }
};

path - встроенный модуль nodeJs предоставляет утилиты для работы с путями к файлам и каталогам.

После объединения выходной файл будет помещен в каталог dist.

Обновите свой package.json файл, напишите в нем раздел scripts.

{
  "name": "react-setup",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "dev": "webpack"
  },
  "devDependencies": {
    "webpack": "^4.5.0",
    "webpack-cli": "^2.0.14",
    "webpack-dev-server": "^3.1.3"
  }
}

Модуль

Пора прикрепить загрузчики к config.module объекту.

Сначала установите babel-cli и babel-loader:

yarn add babel-cli babel-loader

После завершения установки прикрепите babel-loader к массиву module.rules в конфигурации webpack.

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve('./dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  }
};

Плагины

Установите html-webpack-plugin, который генерирует простой html шаблон в свой проект, и включите в него ваше связанное приложение.

yarn add html-webpack-plugin

Создайте template.html файл в корне проекта и вставьте код удара.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app"></div>
</body>
</html>

Поместите html-webpack-plugin в plugins массив объекта конфигурации webpack. Установите опцию шаблона для конфигурации HtmlWebpackPlugin.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // Entry point
  entry: './src/index.js',
  // Output dist
  output: {
    path: path.resolve('./dist'),
    filename: 'bundle.js'
  },
  // Loaders setup
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  },
  // Plugins...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'template.html'
    })
  ]
};

Запустите команду yarn dev, которая построит ваш модуль, и поместите вывод в папку dist. После завершения сборки перейдите в каталог dist и откройте файл index.html в браузере, затем откройте консоль, и вы должны увидеть предупреждение «ОК» в консоли.

Сервер разработки Webpack

Пришло время настроить сервер разработки, чтобы обеспечить перезагрузку в реальном времени после редактирования кода. Отредактируйте webpack.cofing.js файл.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // Entry point
  entry: './src/index.js',
  // Output dist
  output: {
    path: path.resolve('./dist'),
    filename: 'bundle.js'
  },
  // devServer configure
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 8080
  },
  // Loaders setup
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  },
  // Plugins...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'template.html'
    })
  ]
};

Добавьте start скрипт в раздел скриптов package.json файла.

{
  "name": "react-setup",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server",
    "dev": "webpack"
  },
  "dependencies": {
    "babel-cli": "^6.26.0",
    "babel-loader": "^7.1.4",
    "html-webpack-plugin": "^3.2.0"
  },
  "devDependencies": {
    "webpack": "^4.5.0",
    "webpack-cli": "^2.0.14",
    "webpack-dev-server": "^3.1.3"
  }
}

Запустите команду yarn start в терминале, откройте браузер и перейдите к localhost:8080. После этого немного отредактируйте код src/index.js файла, и вы увидите автоматическую перезагрузку в вашем браузере.

Реагировать

Установите в проект библиотеки react и react-dom.

yarn add react react-dom

Создайте файл App.js в каталоге src/components и напишите туда свой первый простой компонент React.

import React from 'react';

export default () => <h1>Hello!</h1>;

Чем нужно рендерить App компонент в dom. Переместитесь в src/index.js file и увлажните компонент App.

import React from 'react';
import { hydrate } from 'react-dom';
import App from './components/App';

hydrate(
  <App />,
  document.querySelector('#app')
);

Сохраните файл, и вы увидите ошибку в консоли браузера и в терминале, например:

Эта ошибка возникает из-за того, что в проекте не установлена ​​предустановка babel react. Перейдите к установке пресета Babel React и Babel preset es2015 в свой проект, а также стадий пресетов.

yarn add babel-preset-react babel-preset-es2015 babel-preset-stage-0 babel-preset-stage-1 babel-preset-stage-2

После установки пресетов создайте файл .babelrc в корне проекта и объявите в нем установленные пресеты.

{
  "presets": ["react", "es2015", "stage-0", "stage-1", "stage-2"]
}

Снова запустите команду yarn start, перейдите к localhost:8080, и вы увидите компонент App в DOM.

Redux

Для использования redux необходимо установить пару библиотек redux. Фактически redux, reduxThunk промежуточное ПО для асинхронных действий и react-redux для передачи частей состояния redux для реагирования компонентов

yarn add redux redux-thunk react-redux

Создайте файл people.js в папке src/reducers, это будет ваш первый редуктор с простым шаблоном без обработки каких-либо типов действий.

const INITIAL_STATE = {
  isFetching: false,
  data: []
};

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    default:
      return state;
  }
}

После этого создайте index.js файл в src/reducers, это будет ваш rootReducer.

import { combineReducers } from 'redux';
import People from './people';

export default combineReducers({
  people: People
});

Осталось подключить rootReducer реагирующее приложение. Откройте файл src/index.js и напишите приведенный ниже код для его достижения.

import React from 'react';
import { hydrate } from 'react-dom';
import App from './components/App';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import reduxThunk from 'redux-thunk';
import rootReducer from './reducers'

const store = createStore(rootReducer, applyMiddleware(reduxThunk));

hydrate(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('#app')
);

Если вы не видите ошибок, все в порядке. Переместитесь к App компоненту и прикрепите к компоненту people фрагмент хранилища.

import React, { Component } from 'react';
import { connect } from 'react-redux';

class App extends Component {
  render() {
    console.log(this.props);
    return <h1>Hello</h1>;
  }
}

const mapStateToProps = ({ people }) => ({ people });

export default connect(mapStateToProps)(App);

Запустите команду yarn start в своем терминале, затем переключитесь в браузер, и в консоли браузера вы увидите данные о людях в реквизитах компонента.

Действия

Пришло время оценить реальную выборку. Я использую SWAPI для игры.

Создайте файл types.js в каталоге src/actions, чтобы объявить типы действий приложения.

export const REQUEST_FETCH_PEOPLE = 'REQUEST_FETCH_PEOPLE';
export const RECEIVE_FETCH_PEOPLE = 'RECEIVE_FETCH_PEOPLE';

Я также axios, чтобы упростить выборку данных.

yarn add axios

Создайте people.js файл в каталоге src/actions и напишите действие fetchPeople.

import axios from 'axios';

import {
  REQUEST_FETCH_PEOPLE,
  RECEIVE_FETCH_PEOPLE
} from './types';


export const fetchPeople = () => dispatch => {
  dispatch({ type: REQUEST_FETCH_PEOPLE });
  axios.get('https://swapi.co/api/people/')
    .then(res => dispatch({ type: RECEIVE_FETCH_PEOPLE, payload: res.data.results }));
};

Это действие отправляет некоторые типы действий, которые вы импортируете из ./types.js файла. Необходимо для обработки этого типа действий people reducer. Перейдите к src/reducers/people.js и измените reducer для обработки типов актина.

import {
  REQUEST_FETCH_PEOPLE,
  RECEIVE_FETCH_PEOPLE
} from '../actions/types';

const INITIAL_STATE = {
  isFetching: false,
  data: []
};

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case REQUEST_FETCH_PEOPLE: {
      return { ...state, isFetching: true };
    }
    case RECEIVE_FETCH_PEOPLE: {
      return { ...state, isFetching: false, data: action.payload };
    }
    default:
      return state;
  }
}

После этого вы можете вызвать действие fetchPeople из App компонента. Откройте действие src/components/App.js file присоедините fetchPeople к функции connect и напишите ловушку componentDidMount.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchPeople } from "../actions/people";

class App extends Component {
  componentDidMount() {
    this.props.fetchPeople();
  }

  render() {
    console.log(this.props);
    return <h1>Hello</h1>;
  }
}

const mapStateToProps = ({ people }) => ({ people });

export default connect(mapStateToProps, { fetchPeople })(App);

Переключитесь в консоль браузера и посмотрите тройной журнал данных о людях. В последнем журнале вы можете видеть, что значение ключа data содержит 10 элементов, это означает, что выборка работает нормально.

Прежде чем мы перейдем к разделу стилей, давайте добавим некоторый шаблон html в компонент App.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchPeople } from "../actions/people";

class App extends Component {
  componentDidMount() {
    this.props.fetchPeople();
  }

  render() {
    const { isFetching, data } = this.props.people;

    if(isFetching) {
      return <span>Loading...</span>
    }

    return <div className="container">
      <ul className="people">
        {data.map(item => <li key={item.name}>
          <span>Name: {item.name}</span>
          <span>Height: {item.height}</span>
        </li>)}
      </ul>
    </div>;
  }
}

const mapStateToProps = ({ people }) => ({ people });

export default connect(mapStateToProps, { fetchPeople })(App);

После этого посмотрите на вкладку вашего браузера и увидите там список людей.

SASS

Чтобы добавить несколько стилей, создайте каталог scss в корне проекта и создайте там файл main.scss. Добавьте некоторые правила стиля в scss/main.scss файл.

body {
  margin: 0;
  padding: 0;
}

.container {
  max-width: 800px;
  padding: 0 16px;
  margin: 48px auto;
}

ul.people {
  list-style: none;
  margin: 0;
  padding: 0;

  li {
    list-style: none;
    padding: 4px;
    margin: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: flex-start;
    border-bottom: 1px solid #34495e;
    transition: box-shadow .2s ease-in-out;

    span {
      color: #2c3e50;
      &:first-child {
        color: #3498db;
        margin-bottom: 4px;
      }
    }

    &:hover {
      box-shadow: 0 4px 8px rgba(0,0,0, .12);
    }
  }
}

Импортировать sass в начало файла App.js.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchPeople } from "../actions/people";
import '../../scss/main.scss';

class App extends Component { ... }

После объединения вы увидите такую ​​ошибку синтаксического анализа:

Последнее, что мы сделаем, это настроим загрузчики стилей в разделе rules файла конфигурации webpack. Сначала установите его.

yarn add style-loader css-loader sass-loader node-sass

После завершения установки создайте правило nu в разделе module.rules в конфигурации webpack и поместите его туда. Наконец, ваш webpack.config.js файл должен выглядеть так.

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // Entry point
  entry: './src/index.js',
  // Output dist
  output: {
    path: path.resolve('./dist'),
    filename: 'bundle.js'
  },
  // devServer configure
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 8080
  },
  // Loaders setup
  module: {
    rules: [
      // Rules for js babel
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      },
      // Rules for css node-sass
      {
        test: /\.scss$/,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader' },
          { loader: 'sass-loader' },
        ]
      }
    ]
  },
  // Plugins...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'template.html'
    })
  ]
};

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

Если ошибок нет, значит все в порядке.

Это все

Вы создали приложение React с управлением магазином redux. Сделано чистым, чтобы понимать конфигурацию веб-пакетов, выборку данных, компиляцию стилей.

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

Код этого проекта хранится в моем репозитории на github.

Спасибо.