# JavaScript

  • Следуем стилю кодирования Airbnb (javascript cs, react.js cs)
  • Используем TypeScript, TSLint и Prettier. Пакет правил tslint-config-airbnb.
  • Следите за единобразием в коде:
    • Названия сущностей должны быть единые по всему приложению (читайте https://martinfowler.com/bliki/UbiquitousLanguage.html)
    • Используем единые компоненты по всему приложению. Например, в react-boostrap есть компоент FormControl, значит используем его всегда, когда нужен input.
    • Структура файлов у компонентов должна быть одинаковая у всех компонентов.

# React.js

:::info Ниже перечислены лишь те соглашения, что не покрываются автоматически TSLint'ом. Не забудьте настроить в своей IDE плагины для TSLint и Prettier. :::

# Структура файлов

Структура директорий должна соотвествовать структуре приложения. Пример:

SmartTable/
    SmartTable.tsx
    styles.css
    Thead/
        Thead.tsx
        styles.css
        TH/
            TH.tsx
            styles.css
  • Пишите короткие имена компонентов. Избегайте префиксов, если какой-то компонент используется изолировано. Например, имя Table может конфликтовать с компонентом библиотеки react-boostrap, но Thead используется изолировано внутри SmartTable.

# Компоненты

  • Предпочитаем React.FunctionalComponent (React.FC) и хуки.
  • Избегайте использования High Order Component, render props. Использование этих шаблонов усложняет код, всё можно сделать нормальной композицией.
  • Если компонент используется лишь в одном месте, делайте его специфическим под текущие требования. Делая компонент универсальным, вы напрасно усложняете код.
  • Имя компонента должно быть существительным и достаточно коротким. Примеры: InvoicesTable, RemoveLicenseButton.
  • Префикс используем только, если имя конфликтует с каким-то глобальным компонентом. Например, Button - есть в boostrap. Добавляем префикс PaymentButton.

# Библиотека общих компонентов

  • Храним в src/ui-components.
  • Добавляем префикс K: KModalWindow.

# Props

Тип для параметров компонента описываем в самом компоненте:

type Props = {
  name: boolean;
  onConfirm(): void;
}

export const PrintInvoiceModal : FC<Props> = ({name = 'default', onConfirm}) => {
    ...
}
  • Порядок перечисления параметров:
    • Обязательные параметры
    • Необязательные параметры
    • Коллбеки
    • Необязательные коллбеки

# Types, interfaces

  • Помните, что типизация - это способ тестирования вашего кода. Не усложняйте код избытком интерфейсов и разных комбинаций интерфейсов.
  • Не экспортируйте типы, если они нужны лишь для проверки входных параметров компонента.
  • Старайтесь не использовать тип any. Альтернативы:
    • Подумайте, может быть объект можно описать типом?
    • Если у объекта множество вариаций атрибутов, заверите в DataObject: const Payload = { [key: string]: any }
    • Используйте generics.
    • Временно отключите типизацию // @ts-ignore и добавьте TODO, чтобы вернуться к коду позже.
  • Предпочитайте использовать type вместо interface. У type меньше возможностей, а значит меньше вероятность усложнить код. Например, если объявить несколько type с одним имененем, будет ошибка.
  • Держим описание типов ближе к компоненту, для которого он написан. Исключением служат типы, которые используются во всем приложении (модели), храните их в в директории src/models.
  • Не определяйте типы там, где TS их определяет сам. Например, в операциях присваивания const text = 'some text';
  • Имена типов пишем без дополнительных префиксов, таких как T* и I*, или *Type

# index.tsx

У библиотек компонентов или моделей, есть смысл завести единую точку импорта index.tsx. Пример:

import * from './SimpleForm';
import * from './SimpleTable';
import * from './SimpleDropdown';

# Тесты

  • Используем Jest.
  • Тесты держим в папке __tests__ или рядом с компонентом (придерживаемся единого вида в рамках проекта). Имя файла с тестами ComponentName.spec.tsx.
  • Покрываем тестами только то, что действительно важно тестировать. Например, бизнес логику проложения.
  • Предпочитаем jest alias'ы: describe() и it().
  • Пишите в describe какой объект тестируется, в it его ожидаемое поведение.
describe("withdraw()", () => {
    it('fetches API', () => {...})
    it('dispatches specific actions', () => {...})
});

# CSS

  • Стили храним вне tsx файла. Имя задаем как styles.{css,sass} или styles.module.css в случае CSS Modules. Один компонент может содержать только 1 файл стилей.
  • Храните стили компонента в папке самого компонента. Если вы хотите выности какие-то классы в общее пространство, то подумайте, не лучше ли создать общий компонент.

# Redux

  • Используем createSlice из Redux Toolkit.

  • Используйте useSelector и useDispatcher вместо connect() (источник).

  • Относитесь к store'у (redux state) как к базе данных:

    • Нормализуйте данные - избегайте дублирования информации.
    • Если состояние сильно изолировано его компонентом, то предпочитайте локальные useState или useReducer.
  • Соблюдайте принцип DRY при написании action'ов. Например, здесь на каждое поле было отдельное действие:

    const editSettingsEmail = (email: string) => {}; const editSettingsPassword = (password: string) => {}; const editSettingsPasswordConfirmation = (passwordConfirmation: string) => {};

Можно заменить одним универсальным:

const updateSettings = (payload: ActionPayload) => {};
  • Избегайте side effects в reducer'ах.
  • Предпочитайте использовать явную немутабельность. В Redux Toolkit встроен Immer, но мы всё равно показываем явное копирование: return {...state, payload}.

# Vue.js

Official Style Guide

  • Все проекты развернуты с использованием Vue CLI. Для небольших проектов используем file-base структуру, которую предоставляет CLI по умолчанию после установки проекта.
  • Если вы понимаете, что ваш проект будет большой, вы можете использовать фрактальную структуру (Module-based).
  • Файлы компонентов создаем в Camel Case стиле, в соответсвие с официальным style guide.
  • В проектах предпочтительно использовать Vue Class Component и TypeScript. Vue CLI позволяет включить данный функционал при установке проекта.
  • Используем стандартную конфигурацию TSLint от Vue CLI.

# Vue 2 -> Vue 3 Migration

Стараемся не использовать данный функционал для сокращения технического долга при миграции проекта на Vue 3:

  • filters;
  • event buses;
  • functional templated
  • slot attributes

Более детально Vue 3 Migration.