Привет, коллеги-энтузиасты React! Сегодня мы углубимся в будничный мир структурирования одностраничного приложения React (SPA). Это часто упускаемый из виду аспект создания приложений, но он может значительно повлиять на ремонтопригодность и масштабируемость вашего проекта.

Я прошел через бесчисленное количество проектов React — некоторые были аккуратно организованы, другие, ну, скажем так, были похожи на коробку с запутанными рождественскими гирляндами. Основываясь на этом опыте, я хотел бы поделиться с вами некоторыми соглашениями и стратегиями, которые хорошо сработали для меня. Итак, пристегнитесь и вперед!

Корневая директория. Отправная точка

Когда вы настроите новый проект React, скажем, используя create-react-app, вы обнаружите, что корневой каталог проекта содержит несколько ключевых файлов и папок. Давайте разберем их:

  • node_modules: Здесь находятся все пакеты, от которых зависит ваш проект. Эти пакеты загружаются при запуске npm install или yarn install. Обычно не рекомендуется изменять этот каталог напрямую или возвращать его в систему управления версиями.
  • public: Эта папка содержит статические файлы, к которым есть общий доступ. Самый важный файл здесь index.html. Это единственный HTML-файл в типичном React SPA, и это файл, который обслуживается при начальной загрузке страницы. Здесь также могут находиться другие статические ресурсы, такие как изображения, шрифты или файл манифеста для установки PWA.
  • src: Здесь живет весь ваш код React. Это сердце вашего приложения React. Внутри вы найдете файлы JavaScript (или TypeScript), файлы CSS (или SCSS), тесты и любые другие ресурсы, которые являются частью вашего приложения и должны быть обработаны Webpack или другими инструментами сборки.
  • package.json: Это важный файл в любом проекте на основе Node.js, включая React. В нем перечислены пакеты, от которых зависит ваш проект, указаны команды для запуска таких задач, как запуск сервера разработки или сборка проекта для производства, а также некоторые метаданные о вашем проекте, такие как его имя и версия.
  • .gitignore: Этот файл сообщает Git, какие файлы или каталоги следует игнорировать в вашем проекте. Как правило, вы игнорируете node_modules, а также любые переменные среды и артефакты сборки.
  • README.md: это файл уценки, в котором вы обычно документируете информацию о своем проекте, например, что он делает, как его установить, как его использовать и т. д.
  • package-lock.json или yarn.lock: эти файлы автоматически генерируются npm или Yarn соответственно. Они блокируют точные версии зависимостей, установленных в node_modules, чтобы обеспечить согласованность во всех средах.

В корне вашего проекта могут быть и другие файлы конфигурации, в зависимости от используемых вами инструментов. Например, файл .babelrc для конфигурации Babel, файл .eslintrc для конфигурации ESLint или файл jest.config.js для конфигурации Jest.

Например, мы рассмотрим большое приложение React, и вам может понадобиться подход «сначала функции», когда вы группируете связанный код по функциям или доменам. Это также известно как «доменно-ориентированный» или «модульно-ориентированный» дизайн. Вот пример:

/my-app
|-- node_modules/
|-- public/
|   |-- index.html
|   |-- manifest.json
|-- src/
|   |-- features/
|   |   |-- User/
|   |   |   |-- components/
|   |   |   |   |-- UserProfile.js
|   |   |   |   |-- UserList.js
|   |   |   |-- services/
|   |   |   |   |-- userService.js
|   |   |   |-- tests/
|   |   |   |   |-- UserProfile.test.js
|   |   |   |   |-- UserList.test.js
|   |   |   |-- UserContext.js
|   |   |   |-- userReducer.js
|   |   |-- Product/
|   |   |   |-- components/
|   |   |   |   |-- ProductList.js
|   |   |   |   |-- ProductDetail.js
|   |   |   |-- services/
|   |   |   |   |-- productService.js
|   |   |   |-- tests/
|   |   |   |   |-- ProductList.test.js
|   |   |   |   |-- ProductDetail.test.js
|   |   |   |-- ProductContext.js
|   |   |   |-- productReducer.js
|   |-- shared/
|   |   |-- components/
|   |   |   |-- Button/
|   |   |   |   |-- Button.js
|   |   |   |   |-- Button.test.js
|   |   |   |   |-- Button.css
|   |   |   |-- Navbar/
|   |   |   |   |-- Navbar.js
|   |   |   |   |-- Navbar.test.js
|   |   |   |   |-- Navbar.css
|   |   |-- utils/
|   |   |   |-- helpers.js
|   |   |-- assets/
|   |   |   |-- images/
|   |   |   |   |-- logo.png
|   |   |   |-- fonts/
|   |   |   |   |-- custom-font.woff
|   |-- App.js
|   |-- index.js
|-- package.json
|-- package-lock.json
|-- .gitignore
|-- README.md

В этой структуре:

  • Код, специфичный для функции, инкапсулирован: каждая функция или домен (например, пользователь, продукт) получает свой собственный каталог в разделе features. Этот каталог содержит все, что связано с этой функцией, включая ее компоненты, службы (например, вызовы API), тесты, поставщик контекста и редуктор (если вы используете что-то вроде Redux или useReducer для управления состоянием).
  • Общий код разделен: код, который является общим для разных функций (например, повторно используемые компоненты, служебные функции, статические активы), хранится в каталоге shared.

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

  • Улучшает обнаружение кода: когда вы работаете над функцией, вы точно знаете, где найти код, связанный с этой функцией.
  • Поощряет совместное использование и повторное использование кода. Разделяя общий код, вы можете легко повторно использовать его в различных функциях.
  • Облегчает параллельную разработку и владение кодом: разные команды или разработчики могут работать над разными функциями, не наступая друг другу на пятки. Также ясно, кому принадлежит какой код.

Помните, что это может варьироваться в зависимости от ваших конкретных потребностей или инструментов, которые вы используете. Например, если вы используете TypeScript, у вас может быть файл tsconfig.json в корневом каталоге для конфигурации TypeScript. Или, если вы используете SCSS, у вас может быть отдельный каталог «styles» для ваших файлов SCSS. Суть в том, чтобы найти структуру и рабочий процесс, которые лучше всего подходят вам и вашей команде.

Папка СРК. Где происходят чудеса

Каталог «src» — это место, где живут все ваши компоненты React и связанный с ними код. Именно здесь вы будете проводить большую часть своего времени в качестве разработчика React. Это сердце вашего приложения React. Внутри вы найдете файлы JavaScript (или TypeScript), файлы CSS (или SCSS), тесты и любые другие ресурсы, которые являются частью вашего приложения.

Конечно, по мере роста приложений потребность в более структурированном и модульном каталоге становится очевидной. Вот пример каталога src для крупномасштабного приложения React:

/src
|-- features/
|   |-- User/
|   |   |-- components/
|   |   |   |-- UserProfile/
|   |   |   |   |-- UserProfile.js
|   |   |   |   |-- UserProfile.test.js
|   |   |   |   |-- UserProfile.module.css
|   |   |-- services/
|   |   |   |-- userService.js
|   |   |-- hooks/
|   |   |   |-- useUser.js
|   |   |-- UserContext.js
|   |   |-- userReducer.js
|-- shared/
|   |-- components/
|   |   |-- Button/
|   |   |   |-- Button.js
|   |   |   |-- Button.test.js
|   |   |   |-- Button.module.css
|   |   |-- Navbar/
|   |   |   |-- Navbar.js
|   |   |   |-- Navbar.test.js
|   |   |   |-- Navbar.module.css
|   |-- utils/
|   |   |-- helpers.js
|   |   |-- tests/
|   |   |   |-- helpers.test.js
|   |-- assets/
|   |   |-- images/
|   |   |   |-- logo.png
|   |   |-- fonts/
|   |   |   |-- custom-font.woff
|-- routes/
|   |-- Home/
|   |   |-- Home.js
|   |   |-- Home.test.js
|   |   |-- Home.module.css
|   |-- About/
|   |   |-- About.js
|   |   |-- About.test.js
|   |   |-- About.module.css
|-- hooks/
|   |-- useTheme.js
|-- App.js
|-- index.js

В этой структуре:

  • Каталог features содержит различные функции или домены приложения. Для каждой функции у нас есть определенные компоненты, сервисы (для вызовов API), хуки, провайдеры контекста и редукторы (если вы используете Redux или хук useReducer).
  • Каталог shared содержит компоненты, утилиты и активы, которые являются общими для нескольких функций приложения.
  • Каталог routes содержит компоненты «страницы», которые представляют различные маршруты в вашем приложении. Каждый маршрут имеет свой собственный файл JavaScript, теста и модуля CSS.
  • Каталог hooks на корневом уровне src содержит настраиваемые хуки, которые используются во многих функциях вашего приложения.
  • App.js — это корневой компонент вашего приложения. Здесь вы должны настроить свои маршруты верхнего уровня и поставщиков контекста.
  • index.js — это точка входа вашего приложения. Здесь вы визуализируете корневой компонент App в DOM.

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

Соглашения об именах. Последовательность является ключевым

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

Вот несколько рекомендаций по соглашению об именах в проекте React:

1. Имена файлов и каталогов

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

  • Используйте PascalCase для имен файлов или каталогов, особенно для компонентов. Например, каталог MyComponent.js или MyComponent/.
  • Используйте «camelCase» для некомпонентных имен файлов, таких как myHelperFunction.js или myService.js.
  • Файлы тестов должны называться <filename>.test.js. Например, MyComponent.test.js.
  • Если вы используете модули CSS, назовите свои файлы CSS как <filename>.module.css. Например, MyComponent.module.css.

2. Названия компонентов:

Имена компонентов React всегда должны начинаться с заглавной буквы. Это требование синтаксиса JSX, поскольку компоненты, начинающиеся со строчной буквы, обрабатываются как встроенные элементы, такие как <div> или <span>.

  • Имена компонентов должны быть описательными и отражать их назначение. Например, UserProfile.js или ProductList.js.
  • Избегайте общих имен, таких как Component1 или DataDisplay.

3. Имена переменных и функций:

Для имен переменных и функций вы должны следовать соглашению об именах JavaScript, которое называется camelCase.

  • Имена переменных должны быть существительными, например const userCount = 5;.
  • Имена функций должны начинаться с глагола, отражающего выполняемое ими действие, например function getUserData() {...}.
  • Логические переменные должны иметь префикс is, has, can или аналогичный, например const isLoading = true;.

4. Названия объектов:

Имена свойств также должны быть в camelCase. Они должны быть описательными и краткими. Как и имена переменных, булевы реквизиты должны начинаться с префикса is, has, can и т. д.

5. Контекст:

Если вы используете Context API, обычно к вашему контексту добавляется суффикс Context. Например, ThemeContext или UserContext.

6. Пользовательские хуки:

Пользовательские хуки всегда должны начинаться со слова use в соответствии с соглашением React. Например, useTheme или useFetch.

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

Компоненты. Разрушая это

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

Функциональные компоненты: это самые простые типы компонентов. Это просто функции JavaScript, которые принимают props в качестве аргумента и возвращают JSX. Например:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

Конечно, давайте подробнее рассмотрим компоненты React.

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

Функциональные компоненты: это самые простые типы компонентов. Это просто функции JavaScript, которые принимают props в качестве аргумента и возвращают JSX. Например:

jsxCopy codefunction Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

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

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

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

Компоненты могут быть как маленькими, как кнопка, так и большими, как целая страница. Ключ к структурированию компонентов в React — сделать их пригодными для повторного использования и поддержки. Вот несколько лучших практик:

  • Принцип единой ответственности: каждый компонент должен делать что-то одно и делать это хорошо. Если компонент начинает становиться слишком большим или сложным, это, вероятно, признак того, что его следует разбить на более мелкие, более управляемые компоненты.
  • Многоразовые компоненты: Компоненты должны быть спроектированы таким образом, чтобы их можно было повторно использовать в максимально возможной степени. Это часто означает сделать их универсальными и передавать данные через пропсы.
  • Типы реквизитов и реквизиты по умолчанию: вы должны определить propTypes для каждого компонента. Это дает понять, какие типы свойств ожидают компонент. Вы также можете определить defaultProps для любых реквизитов, которые имеют значение по умолчанию.
  • Компоненты без состояния и с отслеживанием состояния. Компоненты без состояния (также называемые «тупыми» или «презентационными» компонентами) — это компоненты, которые просто берут свойства и отображают их. Они не управляют и не знают о государстве. Компоненты с состоянием (также называемые «умными» или «контейнерными» компонентами) — это компоненты, которые управляют состоянием и передают его компонентам без состояния через реквизиты.
  • Структура папок компонентов: у каждого компонента должна быть своя папка со всеми связанными файлами. Например:
/Button
|-- Button.js
|-- Button.test.js
|-- Button.module.css

Помните, что это рекомендации, а не строгие правила. Структура ваших компонентов будет зависеть от специфики вашего проекта и предпочтений вашей команды. Самое главное, чтобы ваша структура была четкой, организованной и масштабируемой.

И в этом, друзья мои, прелесть хорошо структурированного проекта React. Поначалу это может показаться тривиальным, но поверьте мне, наличие четкой, организованной структуры проекта может сделать вашу жизнь как разработчика намного проще. Это похоже на хорошо организованное рабочее пространство — вы точно знаете, где что находится, и это значительно повышает вашу производительность и эффективность.

Кроме того, речь идет не только о вас. Если вы работаете в команде, организованная структура сделает совместную работу более гладкой. Ваши товарищи по команде будут вам благодарны, если смогут найти именно то, что ищут, без необходимости перемещаться по лабиринту файлов и папок.

Наконец, помните, что это всего лишь рекомендации, которые, по моему опыту, работают лучше всего. Прелесть разработки программного обеспечения в том, что не существует универсального решения. Самое главное, чтобы структура вашего проекта работала на вас и вашу команду и могла масштабироваться по мере роста вашего проекта.