В прошлых темах весь код приложения был сосредоточен в одном файле, но в реальности, как правило, отдельные компоненты будут размещаться в отдельных файлах. Это упростит разработку и позволит использовать компоненты в других проектах. Однако для веб-страницы лучше, чтобы количество файлов было как можно меньше.
Кроме того, в прошлой теме (да и в ряде других предыдущих тем) мы сталкиваемся с еще одной проблемой - компиляция кода JSX в обычный Javascript на лету занимает некоторое время. Соответственно лучше, если бы у нас был сразу скомпилирован код Javascript до загрузки веб-страницы.
Обе эти проблемы нам поможет решить Webpack. Webpack представляет популярный упаковщик модулей, который позволяет автоматизировать создание из нескольких файлов один.
Для работы с Webpack создадим новый проект. Для этого определим новый каталог webpackapp. Прежде всего сразу установим все необходимые пакеты, которые будут использоваться в проекте. Для этого определим добавим в проект следующий файл package.json:
{ "name": "searchapp", "description": "A React.js project using Webpack", "version": "1.0.0", "author": "metanit.com", "scripts": { "dev": "webpack serve --mode=development", "build": "webpack" }, "dependencies": { "react": "18.0.0", "react-dom": "18.0.0" }, "devDependencies": { "@babel/cli": "7.17.0", "@babel/core": "7.17.0", "@babel/preset-react": "7.16.0", "babel-loader": "8.2.0", "webpack": "5.70.0", "webpack-cli": "4.10.0", "webpack-dev-server": "4.11.0" } }
Среди зависимостей в секции "dependencies" здесь определены две библиотеки - react и react-dom. Эти модули содержат функционал библиотеки React.js, который будет необходим для работы приложения.
В секции "devDependencies" определены те модули, которые потребуются только при разработке приложения.
Так как для компиляции из jsx в js необходим компилятор babel, то вначале определяются соотетстующие модули. Модуль "@babel/core" - это основной модуль компилятора. Для загрузки файлов в webpack необходимы загрузчики, которые собственно и определяют правила загрузки и обработки файлов. Для загрузки файлов добавляется модуль "babel-loader". И этот модуль будет использовать другой модуль - "@babel/preset-react", который необходим для работы в связке с React.js и файлами jsx.
Так как для сборки мы будем использовать Webpack, то в конце добавляется модуль "webpack". Чтобы упростить разработку, добавлен еще один модуль - "webpack-dev-server", который позволяет динамически запускать проект.
Кроме того, в секции scripts определены две команды: dev и build. Команда dev предназначена для нужд разработки и позволяет на лету сгенерировать файл сборки и запустить проект. Команда build позволяет сгенерировать файл сборки, и затем этот файл может использоваться в production.
Далее добавим в проект новую веб-страницу index.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Webpack в React</title> </head> <body> <div id="app"></div> <script src="public/bundle.js"></script> </body> </html>
Здесь, предполагается, что вся функциональность будет находиться в файле по пути "public/bundle.js". Пока этого файла нет, но далее мы его создадим с помощью webpack.
Затем определим в каталоге проекта новую папку app, в этой папке будут находиться собственно файлы приложения.
Для компонентов в папке app создадим подкаталог components. Далее в подкаталог components добавим новый файл header.jsx:
const React = require("react"); function Header(props){ return <h2>{props.text}</h2>;} module.exports = Header;
Данный компонент будет выполнять роль заголовка и будет получать извне через свойства отображаемый текст заголовка.
Поскольку для создания компонентов надо подключить основной модуль react:
const React = require("react");
Для подключения других модулей здесь применяется функция require().
Аналогичный компонент в виде класса:
const React = require("react"); class Header extends React.Component { constructor(props){ super(props); } render() { return <h2>{this.props.text}</h2>; } } module.exports = Header;
И также в каталог app/components добавим новый компонент article.jsx, который просто будет выводить неокторый текст:
const React = require("react"); function Article(props){return <div>{props.content}</div>;} module.exports = Article;
Данный компонент по аналогии получает извне некоторые данные и применяет их при рендеринге.
Аналогичный компонент в виде класса:
const React = require("react"); class Article extends React.Component{ constructor(props){ super(props); } render() { return <div>{this.props.content}</div>; } } module.exports = Article;
Далее в папке app определим главный файл проекта app.jsx - основной файл приложения:
const ReactDOM = require("react-dom/client"); const React = require("react"); const Header = require("./components/header.jsx"); const Article = require("./components/article.jsx"); const header = "Рассказ"; const article = "После одного из заседаний N-ского мирового съезда судьи собрались в совещательной комнате, чтобы снять свои мундиры, минутку отдохнуть и ехать домой обедать."; ReactDOM.createRoot( document.getElementById("app") ) .render( <div> <Header text={header} /> <Article content={article} /> </div> );
Это собственно файл с кодом React, который будет загружать компоненты на веб-страницу.
Вначале импортируем оба компонента:
const Header = require("./components/header.jsx"); const Article = require("./components/article.jsx");
Затем в функции render()
производим рендеринг обоих компонентов, передавая им некоторые данные.
Для работы с webpack добавим в корневую папку проекта новый файл webpack.config.js:
const path = require("path"); module.exports = { mode: "development", entry: "./app/app.jsx", // входная точка - исходный файл output:{ path: path.resolve(__dirname, "./public"), // путь к каталогу выходных файлов - папка public publicPath: "/public/", filename: "bundle.js" // название создаваемого файла }, devServer: { historyApiFallback: true, static: { directory: path.join(__dirname, "/"), }, port: 8081, open: true }, module:{ rules:[ //загрузчик для jsx { test: /\.jsx?$/, // определяем тип файлов exclude: /(node_modules)/, // исключаем из обработки папку node_modules loader: "babel-loader", // определяем загрузчик options:{ presets:[ "@babel/preset-react"] // используемые плагины } } ] } }
Первой в конфигурации идет опция mode
. Ее значение "development"
указывает, что приложение находится в состоянии разработки.
В секции entry: "./app/app.jsx"
указывается главный файл приложения.
Секция output определяет конфигурацию для выходного файла - его папку и имя - public/bundle.js. Это тот файл, который будет подключаться на веб-страницу.
Секция devServer определяют конфигурацию запускаемого веб-сервера, на котором будет развертываться тестируемое приложение.
В частности, значение historyApiFallback: true
указывает, что будет использоваться HTML5 History API. Это может быть полезно, если
приложение использует маршрутизацию.
Опция static
устанавает настройки для статических файлов. В данном случае эта секция нам нужна для установки каталога, где располагается файл
index.html. В частности, параметр directory
указывает, где этот файл находится - в данном случае это корневой каталог проекта,
поэтому применяется путь "/".
Опция port
указывает, что веб-сервер будет запускаться на порту 8081, то есть к приложению мы сможем
обратиться по адресу http://localhost:8081
. А опция open: true
указывает, что при запуске веб-сервера приложение будет автоматически открываться в веб-браузере.
И секция module устанавливает набор загрузчиков, которые будут применяться для загрузки модулей. Здесь определен только один загрузчик - babel-loader. Он будет применяться к файлам с расширением jsx и для обработки будет использовать плагины env и react.
В итоге структура проекта будет выглядеть следующим образом:
В командной строке/терминале перейдем к папке проекта и установим все этим пакеты с помощью команды
npm install
Затем выполним команду
npm run dev
То есть в данном случае выполняем команду, которая определена в секции scripts и которая запускает приложение:
В итоге приложение автоматически будет запускаться в браузере:
С этим приложением мы также можем работать, как и предыдущих темах. Однако чтобы сгенерировать файл приложени - сборку, которая будет содержать код всех файлов, нам надо выполнить другую команду, которая опредена в секции scripts в файле package.json:
npm run build
Эта команда по файлу app/app.jsx создаст в проекте папку public, а в ней - новый файл bundle.js. Это именно тот файл, который будет подключаться на веб-страницу.
То есть будет сгенерирован обычный файл с кодом javascript, который поддерживается всеми браузерами. И нам не понадобится ни компилятор Babel, ни какие-то другие файлы. Мы можем просто кинуть веб-страницу в веб-браузер, и приложение также будет работать.