Существует немало инструментов, позволяющих подготовить среду для React-разработки. Например, в наших материалах учебного курса по React используется средство create-react-app, позволяющее создать шаблонный проект, содержащий всё необходимое для разработки React-приложений. Автор статьи, перевод которой мы публикуем сегодня, хочет рассказать о том, как самостоятельно настроить окружение для разработки React-проектов с использованием Babel и Webpack. Эти инструменты используются и в проектах, создаваемых средствами create-react-app, и мы полагаем, что всем, кто изучает React-разработку, интересно будет познакомиться с ними и с методикой создания React-проектов на более глубоком уровне. А именно, речь пойдёт о том, как сконфигурировать Webpack таким образом, чтобы это средство использовало бы Babel для компиляции JSX-кода в JavaScript-код, и как настроить сервер, используемый при разработке React-проектов.
Webpack
Webpack используется для компиляции JavaScript-модулей. Этот инструмент часто называют «бандлером» (от bundler) или «сборщиком модулей». После его установки работать с ним можно, используя интерфейс командной строки или его API. Если вы не знакомы с Webpack — рекомендуется почитать об основных принципах его работы и посмотреть его сравнение с другими сборщиками модулей. Вот как, на высоком уровне, выглядит то, что делает Webpack.
Работа Webpack
Webpack берёт всё, от чего зависит проект, и преобразует это в статические ресурсы, которые могут быть переданы клиенту. Упаковка приложений — это очень важно, так как большинство браузеров ограничивает возможности по одновременной загрузке ресурсов. Кроме того, это позволяет экономить трафик, отправляя клиенту лишь то, что ему нужно. В частности, Webpack использует внутренний кэш, благодаря чему модули загружаются на клиент лишь один раз, что, в итоге, приводит к ускорению загрузки сайтов.
Babel
Babel — это транспилятор, который, в основном, используется для преобразования конструкций, принятых в свежих версиях стандарта ECMAScript, в вид, понятный как современным, так и не самым новым браузерам и другим средам, в которых может выполняться JavaScript. Babel, кроме того, умеет преобразовывать в JavaScript и JSX-код, используя @babel/preset-react.
Babel
Именно благодаря Babel мы, при разработке React-приложений, можем пользоваться JSX. Например, вот код, в котором используется JSX:
import React from "react";
function App(){
return(
<div>
<b>Hello world!</b>
</div>
)
}
export default App;
Выглядит такой код аккуратно, он понятен, его легко читать и редактировать. Глядя на него, сразу можно понять, что он описывает компонент, возвращающий элемент <div>
, в котором содержится текст Hello world!
, выделенный жирным шрифтом. А вот пример кода, делающего то же самое, в котором JSX не используется:
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function App(props) {
return _react2.default.createElement(
"div",
null,
_react2.default.createElement(
"b",
null,
"Hello world!"
)
);
}
exports.default = App;
Преимущества первого примера перед вторым очевидны.
Предварительные требования
Для того чтобы настроить проект React-приложения, нам понадобятся следующие npm-модули.
- react — библиотека React.
- react-dom — библиотека, которая поможет нам использовать возможности React в браузере.
- babel/core — транспиляция JSX в JS.
- babel/preset-env — создание кода, подходящего для старых браузеров.
- babel/preset-react — настройка транспилятора для работы с React-кодом.
- babel-loader — настройка Webpack для работы с Babel.
- css-loader — настройка Webpack для работы с CSS.
- webpack — сборка модулей.
- webpack-cli — работа с Webpack из командной строки.
- style-loader — загрузка всего используемого CSS-кода в заголовке HTML-файла.
- webpack-dev-server — настройка сервера разработки.
Теперь создадим, в папке react-scratch
, новый проект с помощью npm (npm init
) и установим некоторые из вышеперечисленных пакетов следующей командой:
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader webpack webpack-cli style-loader webpack-dev-server
Точкой входа в программу будет файл index.js
, который содержится в папке src
, находящейся в корневой директории проекта. Ниже показана структура этого проекта. Некоторые файлы и папки создаются автоматически, некоторые вам нужно будет создать самостоятельно.
Структура проекта
Готовый проект, которым мы будем здесь заниматься, можно найти в этом репозитории.
Папка component
будет содержать компоненты проекта (в нашем случае тут присутствует лишь один компонент). В папке dist
, в файле main.js
, будет находиться скомпилированный код, а index.html
— это, как уже было сказано, главный HTML-файл нашего приложения.
Настройка Webpack
Webpack можно настраивать разными способами. В частности, настройки этого инструмента могут принимать вид аргументов командной строки или присутствовать в проекте в виде конфигурационного файла с именем webpack.config.js
. В нём нужно описать и экспортировать объект, содержащий настройки. Мы начнём настройку этого файла с описания объекта, выглядящего так (мы будем рассматривать его по частям, а ниже приведём его полный код):
{
entry: "./src/index.js",
mode: "development",
output: {
filename: "./main.js"
},
}
Свойство entry
задаёт главный файл с исходным кодом проекта. Значение свойства mode
указывает на тип окружения для компиляции (в нашем случае это окружение разработки — development
) и на то, куда нужно поместить скомпилированный файл.
Работа над проектом
Поместим в файл index.html
нашего проекта, расположенный в папке dist
, следующий код:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>React From Scratch</title>
</head>
<body>
<div id="root">
</div>
</body>
<script type="text/javascript" src="main.js">
</script>
</html>
Обратите внимание на тег script
, присутствующий в этом файле. Он указывает на файл main.js
, который будет получен в ходе компиляции проекта. Элемент <div>
с идентификатором root
мы будем использовать для вывода React-приложения.
Теперь установим пакеты react и react-dom:
npm install react react-dom
Внесём в index.js
следующий код:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import App from "./component/app.component";
ReactDOM.render(<App />, document.querySelector("#root"));
Это — стандартный код для подобных файлов React-приложений. Тут мы подключаем библиотеки, подключаем файл компонента и выводим приложение в тег <div>
с идентификатором root
.
Вот код файла app.component.js
:
import React, { Component } from "react";
import s from "./app.component.css";
class MyComponent extends Component {
render() {
return <div className={s.intro}>Hello World</div>;
}
}
export default MyComponent;
Вот код файла app.component.css
:
.intro {
background-color: yellow;
}
Настройка Babel
Babel — это транспилятор, обладающий огромными возможностями. В частности, он умеет преобразовывать LESS в CSS, JSX в JS, TypeScript в JS. Мы будем использовать с ним лишь две конфигурации — react и env (их ещё называют «пресетами»). Babel можно настраивать по-разному, в частности, речь идёт о средствах командной строки, о специальном файле с настройками, о стандартном файле package.json
. Нас устроит последний вариант. Добавим в package.json
следующий раздел:
"babel": {
"presets": [
"@babel/env",
"@babel/react"
]
}
Благодаря этим настройкам Babel будет знать о том, какие пресеты ему нужно использовать. Теперь настроим Webpack на использование Babel.
Настройка Webpack на работу с Babel
Тут мы воспользуемся библиотекой babel-loader, которая позволит использовать Babel с Webpack. Фактически, речь идёт о том, что Babel сможет перехватывать и обрабатывать файлы до их обработки Webpack.
▍JS-файлы
Вот правила, касающиеся работы с JS-файлами (этот код пойдёт в файл webpack.config.js
), они представляют собой одно из свойств объекта с настройками, экспортируемого этим файлом:
module: {
rules: [
{
test: /.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader"
}
},
]
}
В свойстве rules
представленного здесь объекта хранится массив правил, в соответствии с которыми должен быть обработан файл, заданный регулярным выражением, описанным в свойстве test
. В данном случае правило будет применяться ко всем файлам с расширениями .m
и .js
, при этом файлы из папок node_modules
и bower_components
мы транспилировать не хотим. Далее, тут мы указываем, что мы хотим пользоваться babel-loader. После этого наши JS-файлы будут сначала обрабатываться средствами Babel, а потом упаковываться с помощью Webpack.
▍CSS-файлы
Добавим в массив rules
объекта module
настройки для обработки CSS-файлов:
module: {
rules: [
{
test: /.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader"
}
},
{
test: /.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true
}
}
]
},
]
}
Задачу обработки CSS-файлов мы будем решать средствами style-loader и css-loader. Свойство use
может принимать массив объектов или строк. Загрузчики вызываются, начиная с последнего, поэтому наши файлы сначала будут обработаны с помощью css-loader. Мы настроили это средство, записав в свойство modules
объекта options
значение true
. Благодаря этому CSS-стили будут применяться лишь к тем компонентам, в которые они импортированы. Css-loader разрешит команды импорта в CSS-файлах, после чего style-loader добавит то, что получится, в форме тега style
, в разделе <head>
страницы:
<style>
<-- ваш css -->
</style>
▍Статические ресурсы
Продолжим работу над объектом настроек module
, описав в нём правила обработки статических ресурсов:
module: {
rules: [
{
test: /.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader"
}
},
{
test: /.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true
}
}
]
},
{
test: /.(png|svg|jpg|gif)$/,
use: ["file-loader"]
}
]
}
Если система встретит файл с расширением PNG, SVG, JPG или GIF, то для обработки такого файла будет использован file-loader. Обработка таких файлов важна для правильной подготовки и оптимизации проекта.
Настройка сервера разработки
Теперь, в файле webpack.config.js
, настроим сервер разработки:
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
port: 9000,
watchContentBase: true,
progress: true
},
Свойство contentBase
объекта с настройками devServer
указывает на папку, в которой расположены наши ресурсы и файл index.html
. Свойство port
позволяет задать порт, который будет прослушивать сервер. Свойство watchContentBase
позволяет реализовать наблюдение за изменениями файлов в папке, задаваемой свойством contentBase
.
Вот полный код файла webpack.config.js
:
const path = require("path");
module.exports = {
entry: "./src/index.js",
mode: "development",
output: {
filename: "./main.js"
},
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
port: 9000,
watchContentBase: true,
progress: true
},
module: {
rules: [
{
test: /.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader"
}
},
{
test: /.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true
}
}
]
},
{
test: /.(png|svg|jpg|gif)$/,
use: ["file-loader"]
}
]
}
};
Теперь внесём в package.json
, в раздел scripts
, команду для запуска сервера разработки и команду для запуска сборки проекта:
"scripts": {
"dev": "webpack-dev-server",
"start": "webpack"
},
Сейчас всё готово к тому, чтобы запустить сервер разработки следующей командой:
npm run dev
Если теперь перейти по адресу http://localhost:9000, можно будет увидеть страницу нашего проекта.
Страница проекта в браузере
Для того чтобы собрать проект воспользуйтесь следующей командой:
npm run start
После этого можно будет открыть файл index.html
в браузере и увидеть то же самое, что можно было видеть, запустив сервер разработки и перейдя по адресу http://localhost:9000.
Итоги
В этом материале приведён обзор настройки Webpack и Babel для их использования в React-проектах. На самом деле, на той базе, которую мы сегодня разобрали, можно создавать гораздо более сложные конфигурации. Например, вместо CSS можно воспользоваться LESS, вместо обычного JS писать на TypeScript. При необходимости можно, например, настроить минификацию файлов и многое другое. Конечно, если сегодня состоялось ваше первое знакомство с процессом самостоятельной настройки React-проектов, вам может показаться, что всё это очень сложно и куда легче воспользоваться готовым шаблоном. Однако после того, как вы немного в этом разберётесь, вы поймёте, что некоторое увеличение сложности настроек даёт вам большую свободу, позволяя настраивать свои проекты именно так, как вам это нужно, не полагаясь полностью на некие «стандартные» решения и снизив свою зависимость от них.
Уважаемые читатели! Какой подход вы чаще всего используете при подготовке рабочей среды для React-проектов?
Автор: ru_vds