Организация компонентов в проекте

  • Tutorial
Многие руководствуются рекомендациями Presentational and Container Components, но уважаемый автор признаётся в сносках, что концепция разделения спорная, и компоненты можно смешивать. А если это так, то зачем тащить чемодан без ручки? Все компоненты проекта удобнее хранить в одной общей папке. Какие плюсы:
  • Простота навигации по файловой системе.
  • Уникальные имена компонентов проекта.
  • Импорт без боли ('../../../../../..').


Когда проект вырастет, следует дробить его на приватные npm-пакеты, инкапсулируя реализацию. Но не выращивать дерево подпапок внутри папки компонентов — развивать и поддерживать такое ощутимо сложнее. Проверено.

Все компоненты организованы по доменному принципу в одной папке src/componens. Например, можно определить домены: Post — отображение публикации, PostForm — форма редактирования публикации.


Как создать доменный компонент — src/components/Post/Post.js.


Почему нельзя использовать index.js вместо Post.js — соблюдается уникальность имен файлов компонентов внутри проекта, так упрощается навигация по вкладкам редактора (и в WebStorm будет работать ценная функция "Find Usages" для контекстного меню выделенного файла — см. примечание).


Все компоненты в папке доменного компонента получают префикс доменного компонента (Post*.js).


Подпапки в папке доменного компонента не допускаются, внутри плоская структура файлов из компонентов-потомков (PostTitle.js, PostBody.js) и компонентов-предков (PostViewPage.js, PostListPage.js). Компоненты-потомки используются внутри доменного компонента, а компоненты-предки используются снаружи (в роутере, например).


Для импорта доменных компонентов следует задать внутри каждой папки доменного компонента свой package.json, в котором прописать точку входа "main":


{
  "name": "Post",
  "version": "0.0.0",
  "private": true,
  "main": "./Post.js",
}

Кроме того, внутри файла доменного компонента (Post.js) объявлен реэкспорт компонентов-предков:


import PostViewPage from './PostViewPage'
import PostListPage from './PostListPage'
//...
export { PostViewPage, PostListPage }
export default Post

К сожалению, нельзя использовать конструкцию "export from" (ограничение WebStorm), например:


export { default as PostViewPage } from './PostViewPage'

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


import Post from 'components/Post/Post'

По соглашению, разрешается использовать импорт только по имени доменного компонента:


import Post, { PostViewPage, PostListPage } from 'components/Post'

Исходники


Примечание по функции "Find Usages" в WebStorm. Как минимум, есть три контекста использования: 1) по выделенному файлу, 2) по выделенной переменной или символу, 3) по выделенному default в экспорте компонента.


1) Выделим файл components/Post/PostViewPage.js, результат поиска:


// Post.js
import PostViewPage from './PostViewPage'

2) Выделим символ PostViewPage внутри файла PostViewPage.js, результат поиска:


// PostViewPage.js
PostViewPage.propTypes = {}

3) Выделим default в экспорте компонента PostViewPage, результат поиска:


// routes.js
import { PostViewPage } from 'components/Post'
<Route exact path="/post/:id(\d+)/" component={PostViewPage} />

Как видно, третий способ использования выдает наиболее полезную информацию для компонента-предка.


PS


CSS внутри компонентов

Найден правильный способ прикрутить Styled-JSX для Create React App. Теперь CSS-блоки живут внутри файлов компонентов естественным для себя образом — в CSS-формате (против инлайн-стилей JS-объектов). И не нужно беспокоиться за глобальную область видимости.


Абсолютные пути в импорте

Работают относительно папки src, пример:


import MyComponent from 'components/MyComponent'

Конфигурация babel-plugin-module-resolver

['module-resolver', { 'root': ['src'] }]

Настройка WebStorm

Для папки src в контекстом меню выполнить: Mark Directory as > Resource Root.


Настройка Atom

  • Установить плагин js-hyperclick.
  • Для доменных компонентов прописывать в package.json путь до src:
    "moduleRoots": ["../.."]

Настройка VSCode

Нужно добавить jsconfig.json в корень проекта:


{
  "compilerOptions": {
    "target": "ES6"
  },
  "exclude": [
    "node_modules"
  ]
}
Поделиться публикацией

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 13

    0
    В java и c# классы принято называть как, если Page, то MainPage или SomePage, если Model, то UserModel или PostModel. Не понятно чем руководствовался автор, надеюсь что не css стилем.

    Так же не совсем понятна мотивация складывать компоненты в папку components. Ведь все созданное на react по своему определению является компонентами. А желание привести код к повторному использованию должно подтолкнуть на объединение представления-реакт-компонента с логикой этого компонента. Только при таком раскладе можно перенести компонент без боли.

    Так же личный опыт подсказывает, что все проекты уникальны и по сути из проекта в проект мигрируют только ui, которые и следует выносить в отдельный модуль или в случаи со сборщиками в отдельный бандл. А вот компоненты MainPage или PostPage, хотя я называю их MainRoute и PostRoute будут состоять из тех самый ui, а так же будут являться уникальными для конкретного проекта и даже не стоит забивать себе голову чтобы сделать их переиспользуемыми.
      +3

      Я лично предпочитаю использовать index файлы, и у меня Atom он с этим отлично справляется. Думаю WebStorm тоже можно настроить на нормальное отображение файлов во вкладках.


      К тому же у меня в проекте импорты вида:


      import MyComponent from 'components/MyComponent';
      import { getDistributions } from 'actions';

      Достигается это за счёт настройки webpack конфига:


      resolve: {
          extensions: ['', '.jsx', '.js', '.css', '.json'],
          modules: [
            path.resolve('./src'),
            path.resolve('./node_modules'),
          ],
        },

      Если беспокоит линтер, то его тоже можно настроить:


      "settings": {
          "import/resolver": "webpack"
      }

      Более подробно eslint-import-resolver-webpack
      Если интересно более подробно, то могу написать пост.

        –1
        Я лично предпочитаю использовать index файлы

        Экзорцизм в публикации про это, собственно. :)


        Если интересно более подробно, то могу написать пост.

        Конечно интересно!

          +2

          Хорошо, на следующих выходных напишу :) Просто, как мне кажется, создавать package.json файлики в каждом компоненте для исправления поиска и нормального отображения вкладок в IDE, немного изыбтычно, и нужно настраивать саму IDE.


          У меня Атом отображает два одинаковых файла так:


            +2

            WebStorm тоже так умеет, где-то в настройках включается.

              0
              Оно из коробки работает:


              Perfect World:
                0

                Идеально было бы так:


                post/view/.js
                post/view/.test.js
                post/view/.css
                post/view/.tpl
                post/edit/.js
                post/edit/.test.js
                post/edit/.css
                post/edit/.tpl
                  +2
                  > Подпапки в папке доменного компонента не допускаются, внутри плоская структура файлов

                  Проходили. Как следствие размножения подпапок, плодятся компоненты с одинаковыми именами. Можно повеситься, перебирая List.js, Button.js etc. :)
                    0

                    Да нет, нормально получается. Если что, WebStorm умеет и по частям путей искать.

              –1
              и нужно настраивать саму IDE

              IDE подкручивал для навигации по абсолютным путям — в любом случае нужно.

          +1
          Как подстроиться под webStorm. Пользователи Atom, Brackets и VS Code возмущены. Пользователи vim-а снисходительно улыбаются.

          Имхо — строить проект под редактор/IDE — мягко говоря глупость неосмотрительно.
            +1

            Лучше если хоть в одной IDE будет удобно, чем когда неудобно в любой.

              0
              про ложную дихотомию пропустим, перейдем сразу к сути — чем когда неудобно в любой — это от безисходности? Удобно для большинства людей — синоним слова привычно. Если речь об одиночке или фан проекте — да без проблем. Но работать командой с таким подходом — как то не айс.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое