У меня есть сайт React в настоящее время на JavaScript / ES, который мы конвертируем в TypeScript (?). Мы используем структуру «Контейнер» и «Презентация», поэтому каждый компонент будет иметь либо Контейнер и Файл презентации, либо для более простых компонентов просто файл презентации.
В ходе сборки мы обычно создаем "stati *" 1180 * "Сначала презентационные экраны / компоненты, заставьте их пройти контроль качества проектирования, а затем сделайте их динамичными c, добавив Контейнер. Это означает, что файлы презентации обычно создаются первыми. При необходимости контейнеры создаются позже.
Наша структура каталогов выглядит следующим образом:
components
├── SomeComponent
│ └── index.js
│ └── index.jsx
├── SomeOtherComponent
│ └── index.jsx
^^ Здесь у нас есть SomeComponent
, в котором есть Контейнер + Презентация, в то время как SomeOtherComponent
имеет только презентацию.
Эта структура дает нам несколько преимуществ:
- Импорт короткий и не «удваивается»:
import SomeComponent from '../screens/SomeComponent'
( not import SomeComponent from '../screens/SomeComponent/SomeComponent'
) - Импорт не нужно изменять при добавлении контейнеров. Если существует только презентационный файл .jsx, импорт выше работает. Когда / если добавляется файл Container. js, он имеет приоритет над файлом .jsx, поэтому тот же импорт теперь нацелен на новый файл в силу того, что он существует. ( Webpack resolve.extensions = ['. js', '.jsx'] )
- Нет необходимости переименовывать файл презентационного компонента при добавлении контейнера. Это сохраняет историю git в целости и сохранности.
- Быстрая и простая визуальная идентификация того, какой файл является контейнерным или презентационным. Презентационный - это .jsx, потому что там живет наш JSX.
- Мы используем response / jsx-filename-extension , чтобы JSX был только в файлах .jsx . Это дает нашим разработчикам предупреждение eslint, если они попытаются записать JSX в файл контейнера. js. Это обеспечивает соблюдение концепции, согласно которой контейнеры должны выполнять бизнес-логи c (в JS), в то время как Presentations должны просто выводить «тупую» разметку (в JSX).
Отлично работает!
Единственное предостережение, которое, на мой взгляд, очень незначительное, это: Для того, чтобы это работало, в наши Контейнеры мы импортируем презентацию следующим образом: import SomeComponent from './index.jsx'
. Я говорю, что это предостережение просто потому, что это единственное место, где мы импортируем с использованием полного расширения файла. Ничего страшного ...
В TypeScript я бы хотел просто изменить расширение этого файла с js / jsx на ts / tsx вот так:
components
├── SomeComponent
│ └── index.ts
│ └── index.tsx
├── SomeOtherComponent
│ └── index.tsx
Но у нас есть проблема: В TypeScript мы не можем использовать расширения файлов при импорте (насколько мне известно). Таким образом, это нарушает нашу способность выполнять «предостережение» и, кажется, вынуждает нас использовать разные имена файлов для контейнеров и презентаций. ?
Как ваша команда решает эту дилемму?
Я искал соглашения о том, как другие команды решают эту проблему, и пришел с пустыми руками.
Я открыт для критики любой части нашей конвенции здесь, и я приглашаю обсудить. Это проблема более высокого уровня, которая также влияет на повседневную работу наших разработчиков на более низком уровне. Все идеи хорошие (кроме отстойных)!
Несколько идей:
A) ts-ignore
Используйте // @ts-ignore
над строкой import SomeComponent from './index.tsx'
чтобы заглушить ошибку. Это кажется плохой практикой, но каковы будут последствия?
- Плюсы :
- Позволяет использовать index.ts и index.tsx для mimi c наша предыдущая настройка
- Нет необходимости переименовывать презентации при добавлении контейнера
- Нет необходимости изменять импорт при добавлении контейнера
- Минусы :
- Похоже на плохую практику (?)
- Не забудьте добавить его и дать указание другим разработчикам добавить его
- Требуется добавить
'@typescript-eslint/ban-ts-ignore': 'off'
в наш eslint conf, что, в свою очередь, означает, что eslint больше не будет мешать людям использовать @ts-ignore
где угодно. ? - Что еще может сломаться? Убивает intellisense ? Какой еще хаво c может это навредить?
B) PascalCase Presentations
components
├── SomeComponent
│ └── index.ts
│ └── SomeComponent.tsx
├── SomeOtherComponent
│ └── index.tsx
- Плюсы :
- Выглядит довольно условно. Некоторые команды используют PascalCase для всех имен компонентов в качестве соглашения.
- Нет необходимости изменять импорт при добавлении контейнера.
- Минусы :
- Требует переименования презентационного файла при добавлении контейнера (портит git историю).
- Не так просто сразу определить, какой файл является контейнером, а какой - презентационным. Есть (небольшой) логический скачок, который необходимо сделать в вашем уме: «Этот файл назван в честь компонента, а когда они названы в честь компонента, они являются презентационными»).
- Два файла-контейнера / презентационного файла будут не всегда быть «рядом» друг с другом в каталоге. Если существует другой файл с именем index.test.ts, index.stories.tsx или styles. js, он может находиться между index.ts и Presentational.tsx
C) Presentational.tsx
components
├── SomeComponent
│ └── index.ts
│ └── presentational.tsx
├── SomeOtherComponent
│ └── index.tsx
- Плюсы :
- Нет необходимости изменять импорт при добавлении контейнера.
- Мгновенно очевидно, какой файл является презентационным. (Решает проблему с B выше)
- Минусы :
- Требует переименования презентационного файла при добавлении контейнера (портит историю git).
- Два файла-контейнера / презентационного файла не всегда будут находиться «рядом» друг с другом в каталоге. Если существует другой файл с именем index.test.ts или index.stories.tsx, он будет находиться между index.ts и Presentational.tsx
D) index.presentational .tsx
components
├── SomeComponent
│ └── index.ts
│ └── index.presentational.tsx
├── SomeOtherComponent
│ └── index.tsx
- Плюсы :
- Нет необходимости изменять импорт при добавлении контейнера.
- Мгновенно очевидно, какой файл презентационный. (Решает проблему с B выше)
- Два файла-контейнера / презентации всегда будут «рядом» друг с другом в каталоге. (Решает проблему с B & C выше)
- Минусы :
- Требует переименования презентационного файла при добавлении контейнера (мешает с git история).
- Длинное имя файла (не уверен, что меня это действительно волнует)