Если вы используете React, вы, вероятно, также используете create-react-app, что является отличным способом быстрой и простой настройки нового проекта React. Он скрывает всю конфигурацию процесса сборки, поэтому вы можете сразу сосредоточиться на написании кода. Таким образом, вам не нужно беспокоиться о настройке Webpack, Babel и других инструментов сборки. Но делать это вручную может быть очень полезно для целей обучения, поэтому давайте рассмотрим простой способ настройки вашего проекта вручную.

Инициализация проекта

Давайте создадим каталог и инициализируем npm и git.

mkdir react-app
cd react-app
npm init
git init .

Наша структура папок будет выглядеть так:

REACT-APP
└───src
│   └───App.js
│   └───index.js
|   └───index.html
└───package-lock.json
└───package.json
└───webpack.config.json

Итак, мы создадим все необходимые файлы и каталоги.

mkdir src
cd src
touch App.js
touch index.html
touch index.js

Затем нам нужно установить зависимости времени выполнения React.

Настройка React-приложения

Мы добавим контент в файлы в папке src, так что у нас есть работающее приложение React.

index.html

index.js

App.js

Если открытьindex.html в браузере, то там будет пусто. Причина этого в том, что в файле App.js мы используем JSX, когда пишем: return <h1>Hello World</h1>;. Браузер не понимает этот синтаксис, поэтому его необходимо преобразовать из кода JSX в обычный JavaScript. Для этого воспользуемся компилятором Babel.

Вавилонская установка

Во-первых, мы установим ядро ​​Babel и пакеты CLI локально.

npm install --save-dev @babel/core @babel/cli

Используйте предустановку React

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

npm install @babel/preset-react --save-dev

Для настройки Babel мы создадим файл конфигурации babel.config.json в корне проекта.

touch babel.config.json

Внутри файла конфигурации мы определим, какие пресеты мы хотим использовать.

{
  "presets": ["@babel/preset-react"]
}

Тестирование скомпилированного кода

После запуска babel src -d dist скомпилированный код будет находиться внутри папки dist. Чтобы использовать скомпилированный код, нам нужно сослаться на скомпилированный файл index.js в файле index.html. Для этого мы добавим <script src="../dist/index.js" />. Если мы рассмотрим код, скомпилированный Babel, мы увидим, что синтаксис JSX скомпилирован в допустимый код JavaScript.

Стоит отметить, что мы используем модули ES. Поскольку современные браузеры начали изначально поддерживать функциональность модулей, наше приложение должно работать «из коробки». Но если мы откроем index.html в браузере, первая проблема, с которой мы столкнемся, заключается в том, что браузер не распознает index.js как модуль, поэтому мы получаем сообщение об ошибке Uncaught SyntaxError: Cannot use import statement outside a module. Чтобы исправить это, нам нужно включить type="module" в элемент <script>, чтобы объявить этот скрипт как модуль. Наш элемент скрипта будет выглядеть так:

<script type="module" src="../dist/index.js" />

Это должно помочь, верно? Не совсем. Если мы попытаемся запустить страницу еще раз, мы столкнемся со второй проблемой: браузер жалуется, что относительная ссылка модуля React недействительна. Это связано с тем, что браузер принимает только один тип спецификатора модуля в операторе импорта: URL-адрес, который должен быть полностью определенным, или путь, начинающийся с /, ./ или ../. Одним из возможных решений может быть использование относительного пути к модулю React, расположенному в папке node_modules. Но опять же, мы сталкиваемся с другой проблемой. Если вы проверите папку react, то увидите, что React в настоящее время поддерживает только модули UMD и CommonJS. На данный момент мы хотели бы найти какое-то решение, которое позволило бы нам не беспокоиться о форматах модулей зависимостей и о том, как их импортировать. Давайте посмотрим, что предлагает Webpack и какие проблемы он пытается решить.

Настройка веб-пакета

Webapck объединяет все необходимые операции импорта в один файл JavaScript для использования на стороне клиента. Вот почему мы называем это упаковщиком. Поскольку все модули содержатся в одном пространстве имен, это решает для нас все проблемы с зависимостями и форматом модуля. Другими важными особенностями, о которых стоит упомянуть, являются:

  • Механизм встряхивания дерева — он может исключить код, который не используется и не импортируется каким-либо другим модулем.
  • Разделение кода — может создавать несколько пакетов, которые можно динамически загружать во время выполнения.

Чтобы начать использовать Webpack, нам сначала нужно установить необходимые пакеты:

npm install webpack webpack-cli --save-dev

Мы устанавливаем 2 пакета: основной пакет Webpack и webpack-cli для запуска команд Webpack.

Далее добавим файл конфигурации Webpack:

touch webpack.config.js

Начнем с базовой конфигурации:

Что тут происходит? Во-первых, мы определяем точку входа приложения. Это точка, с которой Webpack начинает процесс объединения и строит дерево зависимостей. В нашем случае точкой входа будет файл index.js. Кроме того, мы определяем выходной путь для связанного файла. Мы будем использовать папку dist в качестве выходного пути.

Поскольку у нас настроена базовая конфигурация, мы можем создать приложение с помощью интерфейса командной строки Webpack. Мы можем использовать команду webpack build, но так как это команда по умолчанию, мы можем использовать только webpack. Но если мы попытаемся запустить эту команду, Webpack выдаст что-то вроде этого:

Module parse failed: Unexpected token (5:16)
You may need an appropriate loader to handle this file type, currently, no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import App from "./App";
| 
> ReactDOM.render(<App />, document.getElementById("app"));
|

Webpack сообщает нам, что он не распознает синтаксис JSX и что для правильной обработки ему требуется нечто, называемое загрузчиком. Итак, давайте посмотрим, как это сделать.

Настройка загрузчика Babel

По умолчанию Webpack понимает только файлы JavaScript и JSON. Загрузчики позволяют Webpack понимать другие типы файлов. Для файлов JSX мы будем использовать загрузчик Babel. Мы уже установили и использовали базовый пакет и пресеты Babel. Теперь нам нужно установить загрузчик.

npm install babel-loader --save-dev

Затем мы можем изменить конфигурацию Webpack, чтобы начать использовать загрузчик Babel. Файл конфигурации будет выглядеть так:

Поскольку рабочий режим минимизирует код по умолчанию, мы будем использовать режим разработки из-за удобочитаемости вывода. Ниже приведены пояснения для некоторых других используемых свойств:

  1. test определяет, какой файл или файлы следует преобразовать
  2. exclude определяет, какие модули следует исключить
  3. use указывает, какой загрузчик следует использовать для преобразования
  4. presets — это список пресетов, которые следует использовать

Теперь Webpack должен быть удовлетворен и успешно запустит команду сборки. Если мы посмотрим на выходной пакет, то увидим, что Webpack упаковал наши модули приложения и модули React в один файл. Теперь мы можем использовать этот пакет в index.html, добавив тег script:

<script src="../dist/main.js" />

Если вы сейчас откроете файл index.html в браузере, вы увидите сообщение Hello World. Это означает, что наше приложение запущено и работает. Это мило 😌 . Давайте посмотрим, как мы можем оптимизировать процесс сборки.

Настройка плагина HtmlWebpack

Прямо сейчас мы включаем пакет в файл index.html вручную. Этого достаточно для запуска нашего приложения. Но в реальных приложениях мы могли бы использовать разделение кода, которое создавало бы несколько пакетов, или мы могли бы даже хэшировать имена файлов пакетов для целей кэширования. Было бы утомительно включать их вручную в наш index.html каждый раз при создании пакетов. Поэтому мы автоматизируем этот процесс с помощью HtmlWebpackPlugin. Плагины — это сторонние пакеты, которые можно использовать с Webpack для расширения его функциональности. В данном случае мы используем HtmlWebpackPlugin. Во-первых, давайте установим его:

npm install html-webpack-plugin --save-dev

Затем измените файл конфигурации:

После запуска команды сборки вы заметите, что теперь в папке dist есть также файл index.html. И самое главное, тег скрипта main.js вставляется автоматически. Это означает, что мы можем удалить тег <script> из src/index.html.

Настройка сервера разработки

В настоящее время мы собираем пакет вручную после каждого изменения и открываем index.html, чтобы увидеть результаты в браузере. Это, конечно, не идеальное решение для среды разработки, и было бы лучше, если бы мы могли автоматизировать эти шаги. Webpack предлагает специальный пакет под названием webpack-dev-server, который действует как сервер разработки и поддерживает перезагрузку в реальном времени. Таким образом, мы сможем разместить наш пакет, и любое изменение в коде приведет к перезагрузке нашего приложения в браузере.

Здесь важно упомянуть, что сервер разработки создает отдельный пакет JavaScript и выводит его в памяти. Он будет отслеживать зависимости точки входа, определенной в конфигурации Webpack, и воссоздавать выходные данные при обнаружении изменений. Мы будем использовать этот вывод при обслуживании приложения в среде разработки, а не вывод, созданный интерфейсом командной строки Webpack. Во-первых, давайте установим необходимый пакет:

npm install webpack-dev-server --save-dev

Далее нам нужно настроить dev-сервер в конфигурационном файле Webpack:

Это базовая конфигурация, которая позволит нам разместить приложение локально. Во-первых, мы определяем port, на котором будет работать сервер. После этого мы устанавливаем для свойства open значение true, что означает, что сервер разработки откроет приложение в браузере по умолчанию после запуска сервера. Запускаем браузер командой webpack serve. Приложение будет открыто в браузере, и любые изменения в коде автоматически и мгновенно появятся в браузере. Помните, что сервер разработки обслуживает выходные данные в памяти, поэтому даже если вы очистите содержимое выходной папки, страница все равно будет работать.

Заключение

В этой статье мы рассмотрели основы экосистемы Webpack. Мы увидели, как инициализировать проект React с нуля и как использовать транспилятор Babel. Кроме того, мы узнали о загрузчиках Webpack, плагинах и о том, как использовать сервер разработки Webpack. Конечно, это только основы, и есть гораздо больше концепций, которые нужно изучить об экосистеме Webpack. О некоторых из них я расскажу в следующих постах.

Вы можете посмотреть пример репозитория здесь.