asb_cloud_front/CODE_STANDART.md

11 KiB
Raw Permalink 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 - для компонентов, применяющихся как виджеты в дашбордах.