asb_cloud_front/CODE_STANDART.md

11 KiB
Raw Blame History

1. Общие положения

  1. Все несамостоятельные компоненты должны быть написаны на TypeScript. Для самостоятельных компонентов (использующихся как страницы) (далее страницы) допускается использование JavaScript для ускорения написания;

1.1. Файловая структура проекта

  1. Компоненты должны распределяться по директориям в соответствии со своим назначением:
    • src/context - Для контекстов приложения;
    • src/components - Для несамостоятельных компонентов, применяющихся многократно;
    • src/pages - Для страниц и компонентов, использующихся исключительно в единственном экземпляре;
    • src/images - Для компонентов-изображений.
  2. Если страница описывается 1 файлом она должна именоваться в соответствии с содержимым, в ином случае должна быть создана директория с соответствующим названием, внутри которой будут находиться файлы страницы. Основной файл в таком случае должен быть переименован в index.jsx;
  3. Файлы именуются в соответствии с таблицей:
    Тип содержимого файла Расширение Стиль именования
    Компонент или страница jsx/tsx PascalCase
    Файл стилей css/less snake_case
    Вспомогательные методы или константы js/ts snake_case
    Описательные документы md SCREAMING_SNAKE_CASE

1.2. Стилизация кода

  1. Все строки должны по возможности описываться одинарными кавычками или при необходимости обратными:
        const name = 'world'
        const msg = 'Hello, \'' + name + '\'!'
        const toPrint = `Message: ${msg}`
    
  2. Все переменные по возможности должны инициализироваться как const, применение var не допускается;
  3. Переменные именуются в соответствии с таблицей:
    Тип переменной Стиль именования
    Метод, переменная camelCase
    Константы SCREAMING_SNAKE_CASE
    Компонент PascalCase

1.3. Импортирование / Экспортирование

  1. Импортированные файлы (в том числе lazy import) необходимо указывать в самом верху документа в следующем порядке с разделением пустой строкой:
    1. Внешние зависимости (react, antd, webpack и т.д.);
    2. Локальные компоненты по порядку:
      1. Контексты (@asb/context);
      2. Компоненты (@components/Table);
      3. Вспомогательные методы (@utils);
      4. Сервисы API (@api).
    3. Изображения и компоненты-изображения (@images);
    4. Стили (@styles);
    5. Lazy import (const page = React.lazy(() => import('./page'))).
  2. При импорте локальных файлов стоит пользоваться alias'ами:
    Путь Alias
    src/components @components
    src/context @asb/context
    src/images @images
    src/pages @pages
    src/services/api @api
    src/styles @styles
    src/utils @utils
  3. По возможности импортировать из пакетов и файлов только использующиеся сущности:
    // вместо
    import React from 'react'
    const page: React.ReactNode = React.lazy(() => import (...))
    
    // стоит использовать
    import { lazy, ReactNode } from 'react'
    const page: ReactNode = lazy(() => import (...))
    

2. JS

  1. Методы, константы и переменные документируются в соответствии с JSDoc;
  2. При документации страниц необходимо указать её название, краткое описание и описание получаемых параметров:
    import { memo } from 'react'
    
    import LoaderPortal from '@components/LoaderPortal'
    
    /**
     * Тестовая страница
     *
     * @description Данная страница не имеет смысла и просто выводит переданное название и контент
     * @param title - Название страницы
     * @param content - Контент страницы
     * @param loading - Отображать ли оверлей загрузки над блоком страницы
     */
    export const TestPage = memo(({ title, content, loading }) => (
        <LoaderPortal show={loading}>
            <div className={'dd-test-page'}>
                <div className={'dd-test-page-title'}>{title}</div>
                <div className={'dd-test-page-content'}>{content}</div>
            </div>
        </LoaderPortal>
    ))
    
    export default TestPage
    

3. TS

  1. Методы, константы и переменные документируются в соответствии с TSDoc;
  2. При документации компонентов необходимо указать их название, краткое описание, а также описать параметры в типе:
    import { memo } from 'react'
    
    import LoaderPortal from '@components/LoaderPortal'
    
    export type TestPageProps = {
        /** Название страницы */
        title: ReactNode
        /** Контент страницы */
        content: ReactNode
        /** Отображать ли оверлей загрузки над блоком страницы */
        loading: boolean
    }
    
    /**
     * Тестовая страница
     *
     * @description Данная страница не имеет смысла и просто выводит переданное название и контент
     */
    export const TestPage = memo<TestPageProps>(({ title, content, loading }) => (
        <LoaderPortal show={loading}>
            <div className={'dd-test-page'}>
                <div className={'dd-test-page-title'}>{title}</div>
                <div className={'dd-test-page-content'}>{content}</div>
            </div>
        </LoaderPortal>
    ))
    
    export default TestPage
    
  3. Использование any в типах допустимо только, если значение используется только в параметрах компонентов, обозначенных типом any. Если метод предполагает работу с разными типами значений стоит описать его как обобщённый.

4. JSX/TSX

4.1. Стилизация кода

  1. Все указываемые к компоненту параметры должны быть обёрнуты в фигурные скобки, кроме параметров флагов со значением true:
    <Button disabled title={'Hello, world!'} type={'ghost'}>Click me!</Button>
    
  2. Если описание параметров компонента не укладывается в ширину в 120 строк стоит перенести их в соответствии с шаблоном:
    <Button
        disabled
        title={'Hello, world!'}
        type={'ghost'}
    >
        Click me!
    </Button>
    
  3. Если JSX код передаётся как значение стоит обернуть его в круглые скобки:
        const a = (
            <Button disabled title={'Hello, world!'} type={'ghost'}>Click me!</Button>
        )
    

4.2. Логика поведения

  1. Не допускается создание значений ссылочных типов в области рендера. Они должны быть вынесены в переменные или константы;
  2. Не допускается создание переменных в функциональных компонентов без использования хуков useMemo/useCallback/useState;
  3. Если переменные или методы не имеют зависимостей и не вызывают методы, доступные исключительно внутри компонента, они должны быть вынесены выше кода компонента.

5. LESS

  1. Использование id должно быть сведено к минимуму;
  2. Все классы именуются с префиксом компании "dd-";
  3. Слова в классах разделяются тире ("-");
  4. Файлы именуются в соответствии с компонентом, к которому относятся;
  5. В одном файле описываются стили либо к конкретному компоненту, либо к странице;
  6. Файл со стилями должен подключаться не более чем к одному компоненту (странице);
  7. Файлы поделены на директории виду компонента, к которому применяются стили:
    • styles/components - для компонентов, не использующихся самостоятельно;
    • styles/pages - для компонентов, использующихся как страница;
    • styles/widgets - для компонентов, применяющихся как виджеты в дашбордах.