Всем привет!

Написать эту публикацию меня побудила вот эта недавняя статья (вчера увидел).

Пересказывать основные признаки Headless/content-first/api-first и т.п. CMS я не буду, материала полно и наверняка уже многие знакомы с этим трендом. А хочу я рассказать почему и как я пишу свою систему, почему не смог выбрать из имеющихся, что я думаю о других системах, с которыми сталкивался ранее и какие вообще на все это перспективы вижу. Чтиво будет объемное (ибо материал за два года), но постараюсь написать побольше интересного и полезного. Кому интересно, прошу под кат.

Вообще история реально долгая и я постараюсь ее рассказать сначала. То ли чтобы было более понятно каковы истинные причины для создания этого своего движка, то ли потому что просто без этого сложно будет на местах пояснять почему я делаю это именно так, а не эдак.

Но для начала я все-таки коротко распишу основные критерии отбора современной Headless-CMS лично для меня, почему же я все-таки так и не смог выбрать для себя уже готовое решение. Просто чтобы народ не обламывался читать много буков, не понимая, что же в итоге-то будет рассказано.

Коротко: хотелось чтобы все было в одном месте: и бэк, и фронт (а не или то, или другое), и GraphQL-API, и чтобы база данных управляемая была и еще много всего, включая кнопку «Сделать красиво». Вот этого и не нашел. Сам я такое тоже не сделал еще, но в целом уже получилось очень даже не мало, а главное, позволяет делать реальные проекты.

И так, мой подход скорее всего вряд ли можно назвать научным и обоснованным. Дело в том, что я вообще очень часто пишу что-то свое. Нравится вот мне программировать. И два года назад (и до этого еще 8 лет) я сидел на MODX CMF (под которую тоже много своих костылей изобрел). И вот три года мы затеяли один довольно масштабный проект, под который, как мне казалось, я смогу использовать MODX. Но как оказалось, не смог… Основная причина была в том, что это был стартап без какого-либо ТЗ, с кучей идей, которые менялись и дополнялись каждый день (и по нескольку раз на день). И вот каждый раз, когда под новую идею надо было добавить какую-то новую сущность, прописать/изменить поля для имеющихся, создать/удалить/изменить связи между этими сущностями (соответственно с изменением структуры базы данных), у меня в какой-то момент стало уходить по несколько часов на изменение этих сущностей. Ведь помимо того, что надо было прописать эти изменения в схеме, надо было изменить базу данных (практически вручную), актуализировать API, переписать программный код и т.д и т.п. Соответственно, и фронт надо было под все это актуализировать. В итоге я решил, что надо искать что-то новое, более удобное, позволяющее как-то все это упростить. Еще раз уточню, что на тот момент я был php бэкэндщиком, так что не удивляйтесь и не смейтесь, что я стал открывать для себя различные сборщики фронта, less-процессоры, npm и т.д. и т.п. Но так или иначе, постепенно в нашем проекте появился фронт на react+less, API на GraphQL, а сервер на express.

Но не все так было радужно, как это многим показалось бы сейчас. Напомню, это было более двух лет назад. Если вы в современном JS-вебе менее двух лет, советую к прочтению вот эту статью: N причин, чтобы использовать Create React App (habr). Кому лень, коротко: с появлением react-scripts можно не заморачиваться с конфигурированием webpack и т.п. Все это уходит на задний план. Добрые ребята уже сконфигурировали webpack так, чтобы на нем почти гарантированно работало большинство react-проектов, а конечный разработчик сосредотачивался непосредственно на программировании конечного продукта, а не конфигурировании кучи зависимостей, loader-ов и т.п. Но это уже позже. А до этого мне как раз приходилось конфигурировать этот webpack, следить за обновлении кучи всего того, что летело с ним в догонку и т.д. и т.п. А ведь это только часть работы, только по сути фронт. А еще нужен сервер. А еще нужно API. А еще нужно SSR (Server-side rendering), который, к слову, react-script до сих пор не обеспечивает, на сколько я знаю. В общем, все было тогда гораздо сложнее, чем сейчас, многого не было, и каждый костылил как мог. А как я тогда костылил…

Только представьте:

  • Собственная конфигурация webpack отдельно для фронта и сервера.
  • Собственная реализация SSR, так, чтобы async нормально работал с react-server, и стили сразу готовые прилетали, и индексировалось нормально, и статусы серверные для ненайденных страниц отдавались.
  • No-redux. Ну не понравился мне redux вот сразу. Больше понравилась идея использовать родной реактовый flux (хотя и его пришлось под себя чуть-чуть переписать).
  • Вручную прописанные GraphQL-схемы и резолверы, без автоматического деплоя базы данных (API-сервер использовался как миддл для MODX-сайта).
  • Никаких react-apollo/apollo-client и т.п. Все написано самостоятельно с запросами через fetch, хранилищами в браузере на базе custom flux.

Как результат: до сих пор на одной из первых версий этого работает один проект с посещаемостью 500+, а в сезон (зимой) 1000-1700 уников в день. Uptime 2 месяца. Это потому что сам я вручную сервер перезагружал после профилактического обновления ПО. А до этой перезагрузки uptime еще 6+ месяцев был. Но самое интересное — это потребление памяти. В настоящий момент почти 700 мегабайт js-процесс. Да-да, я здесь тоже с вами смеюсь:) Конечно же это очень много. А до этого я еще небольшую профилактику делал и улучшил этот показатель. Раньше было и вовсе 1000M+ на процесс… Тем не менее оно работало и вполне так себе сносно. При чем до того, как в ноябре гугл изменил алгоритмы PageSpeed Insights, у сайта был показатель производительности 97/100. Пруф.

Промежуточный вывод на основании этого проекта на базе системы, которая развивалась далее уже без этого проекта (проект остался позади):

Плюсы

  1. API проекта стало более гибкое за счет использования GraphQL, а количество запросов на сервер значительно сократилось.
  2. Проекту открыт доступ к огромному количеству компонентов на npm.
  3. Управление проектом стало более прозрачным за счет использования зависимостей, гита и т.п.
  4. Сбилденные в кучу скрипты и стили конечно же больше радуют, чем куча отдельных скриптов на старых сайтах, когда и не знаешь что из этого зоопарка можно убрать без последствий (и не редко наблюдаешь на одном сайте несколько версий жучки).
  5. Сайт стал более интерактивный, страницы работают без перезагрузки, возврат на ранее просмотренные страницы не требует повторных обращений к серверу.
  6. Редактирование данных происходит прям на странице, по принципу «редактируй то, что видишь и там, где видишь», без какой-либо отдельной админки.

Минусы (в основном для разработчика)

  1. Все очень сложно. Реально. Подключить к проекту какого-то стороннего разработчика просто нереально. Я и сам с трудом разбирался что и как работает и откуда растут ноги. Если смотреть п. 3 из плюсов, где сказано про прозрачность, то прозрачность только в том, что если где-то что-то зацепишь, сразу видно, что сломано (скрипты не билдятся и т.п.), а по коммитам и диффам можно найти где что зацепил. Ну и если удалось добавить что-то новое и оно работает, хотя бы понимаешь четко, что да, все залетело нормально. Но в целом это все равно адский ад.
  2. Сложности с кешированием. Это потом я уже для себя открыл apollo-client. А до этого, как я и говорил, писал свои хранилища на базе flux. За счет этих хранилищ получалось из разных компонентов получать нужные данные для рендеринга, но объем кеша на стороне клиента был очень большой (для каждого набора сущностей типовых было свое хранилище). В итоге, сложно было обеспечить проверку того, был ли объект запрошен ранее или нет (то есть стоит ли запрос на сервер делать чтобы его найти), все ли данные связанные имеются в наличии и т.п.
  3. Сложности со схемами, структурой БД и резолверами (API-функциями получения/изменения данных). Как я и говорил, схемы я писал вручную, и резолверы тоже. При чем в резолверах я пытался и кеширование обеспечить, и обработку вложенных запросов и прочие тонкости. В тот момент мне пришлось очень глубоко погрузиться в суть и программный код GraphQL. Плюс на выходе в том, что я в целом довольно хорошо понимаю, как работает GraphQL, какие у него плюсы и минусы и как его лучше готовить. Минус в том, что конечно же нельзя в одного написать все те удобства и плюшки, написанные командами типа apollo. В итоге, когда я открыл для себя apollo, конечно же я с большим удовольствием стал использовать их компоненты (но в основном на фронте, ниже расскажу почему).

В общем, этот проект на устаревших технологиях лично мой на 100%, поэтому я могу себе позволить его забросить до лучших времен. Но есть другие проекты, ради которых пришлось идти дальше и платформу развивать. И несколько раз приходилось переписывать все практически с нуля. Далее я буду более подробно рассказывать об отдельных задачах, с которыми сталкивался и какие решения в итоге разрабатывал и применял.

Schema-first. Сначала схема, а потом все остальное

Сайт (веб-интерфейс, тонкий клиент и т.п.) — это все отображение информации (ну и управление информацией, если позволено и функционал позволяет). Но сначала все-таки база данных (таблицы, колонки и т.п.). Встретив на своем пути несколько различных подходов к работе с базой данных, мне больше всего понравился подход Schema-first. То есть описываешь схему сущностей и типов данных (вручную или через интерфейс), деплоишь схему и у вас сразу в базе данных применяются описанные изменения (создаются/удаляются таблицы и колонки, а так же связи между ними). В зависимости от реализации у вас еще и будут сгененрированы все необходимые функции-резолверы для управления этими данными. Больше всех в этом направлении мне понравился проект prisma.io.

С вашего позволения, так как даже на хабре я не встретил ни одной статьи про призму, я чуть-чуть заострю на них внимание, так как проект действительно очень интересный, и без них у меня бы не было сейчас такой платформы, которая меня так радовала. Собственно, поэтому я свою платформу и назвал prisma-cms, потому что prisma.io играет очень большую роль в нем.

Собственно, prisma.io — это SaaS-проект, но с большой оговоркой: практически все, что они делают, они выкладывают на гитхаб. То есть, вы можете воспользоваться их серверами за вполне разумную плату (и сконфигурировать под себя собственную базу данных и API в считанные минуты), а можете полностью развернуть все у себя. При этом призму логически надо поделить на две важных отдельных части:

  1. Prisma-server, то есть тот сервер, где еще и база данных крутится.
  2. Prisma-client. Это по сути тоже сервер, но по отношению к источнику данных (prisma-серверу) является клиентом.

Сейчас я постараюсь объяснить эту запутанную ситуацию. В общем, суть призмы в том, чтобы используя один API-endpoint, можно было работать с различными источниками данных. Да, здесь любой скажет, что это все придумали в GraphQL и prisma тут не нужна. В целом все будут правы, но есть серьезный момент: GraphQL только определяет принципы и общую работу, но сам по себе он из коробки не обеспечивает работу с конечными источниками данных. Он говорит «Вы можете создать API-схему, чтобы описать какие запросы смогут слать пользователи, но как вы будете обрабатывать эти запросы, это уже вы сами будете заморачиваться». И призма тоже конечно же использует GraphQL (к слову, и много еще чего другого, включая различные apollo-продукты). Но призма плюс к этому как раз и обеспечивает работу с базой данных. То есть описывая схему и деплоя ее, в указанной базе данных сразу будут созданы нужные таблицы и колонки (а так же связи между ними), да еще и генерит сразу все необходимые CRUD-функции. То есть с призмой вы не просто получаете GraphQL-сервер, а полноценное работающее API, которое сразу позволяет работать с базой данных. Так вот, Prisma-server обеспечивает работу базу данных и взаимодействие с ней, а prisma-client позволяет писать свои резолверы и слать запросы на prisma-server (или еще куда-нить, хоть на несколько prisma-server). И вот получается, что у себя вы можете развернуть только prisma-client (а в качестве prisma-server будет использоваться SaaS prisma.io), а можете развернуть prisma-server у себя, и вообще никаким образом не зависеть от призмы, это будет все ваше.

Вот призму я для себя и выбрал, как основу для своей платформы. Но далее пришлось и это докручивать для себя, чтобы получить полноценную платформу.

1. Мерж схемы


На тот момент призма не умела объединять схемы. То есть задача в следующем:

У вас в одном модуле описана модель пользователя

type User {
  id: ID! @unique
  username: String! @unique
  email: String @unique
}

и в другом модуле

type User {
  id: ID! @unique
  username: String! @unique
  firstname: String
  lastname: String
} 

В рамках одного проекта вы хотите объединить эти две схемы автоматически, чтобы получить на выходе

type User {
  id: ID! @unique
  username: String! @unique
  email: String @unique
  firstname: String
  lastname: String
}

Вот тогда этого призма не умела делать. Получилось это реализовать с помощью библиотеки merge-graphql-schemas.

Работа с произвольным prisma-server.


В призме конфигурация прописывается в специальном конфиг-файле. Если хочешь изменить адрес используемого призма-сервера, надо править файл. Мелочь, а не приятная. Хотелось сделать, чтобы УРЛ можно было указывать в команде, например endpoint=http://endpoint-address yarn deploy (yarn start). Вот на это было убито несколько дней… Но зато теперь можно один призма-проект использовать для любого количества эндпоинтов. К слову, до сих пор prisma-cms легко работает хоть с локальной базой, хоть с SaaS серверами призмы.

Модули/плагины


Вот этого вообще сильно не хватало. Как я говорил, основная задача призмы — это обеспечивать работу с различными базами данных. И они с этим отлично справляются. Уже сейчас они поддерживают работу с MySQL, PostgreSQL, Amazon RDS и MongoDB, еще несколько типов источников на подходе. Но они не дают никакой модульной инфраструктуры. Нет пока никакого маркетплейса или типа того. Есть только несколько типовых заготовок. Но вы не можете из нескольких заготовок выбрать две-три и установить на один проект. Придется выбирать какую-то одну. Я же хотел, чтобы можно было на конечном проекте устанавливать различное количество модулей, и чтобы при деплое схемы и резолверы мержились и получался такой единый проект с суммарным функционалом. И хотя какого-то графического интерфейса пока нет, есть уже больше двух десятков работающих модулей и компонентов, которые можно комбинировать на конечном проекте. Здесь сразу немного определюсь с личными определениями: модуль — это то, что устанавливается на бэк (расширяя базу данных и API), а компонент, это то, что устанавливается во фронт (для добавления различных элементов интерфейса). Пока что для подключения модулей тоже нет графического интерфейса, но мне не сложно прописывать так (это же не часто делается):

  constructor(options = {}) {

    super(options);

    this.mergeModules([
      LogModule,
      MailModule,
      UploadModule,
      SocietyModule,
      EthereumModule,
      WebrtcModule,
      UserModule,
      RouterModule,
    ]);

  }

После добавления новых модулей достаточно просто выполнить опять деплой одной командой и все, вот у нас уже новые таблицы/колонки и дополненный функционал.

5 фронт, реагирующий на изменения в бэкэнде


Вот этого вообще не хватало. Тут последует лирическое отступление. Дело в том, что все API-first CMS, что я видел, говорят «Мы офигенно обеспечиваем API, а вы прикручивайте какой хотите фронт». Вот это их «прикручивайте какой хотите» на самом деле по факту означает «заморачивайтесь как хотите». Ровно так же, как UI-фреймворки говорят «смотрите какие мы классные кнопочки и все такое делаем, а с бэкэндом заморочьтесь сами». Вот это всегда убивало. Хотелось найти просто комплексную CMS, написанную на javascript, использующую GraphQL и обеспечивающую сразу и бэк, и фронт. Но вот не нашел я такой. А очень хотелось, чтобы изменения API сразу актуально воспринимались и на фронте. И вот для этого было еще выполнено несколько подшагов:

5.1 Генерация API-фрагментов


На фронте в запросах прописаны фрагменты из схема-файла. Когда на сервере API пересобирается, генерируется и новый JS-файл с API-фрагментами. А в запросах прописано типа такого:

const {
  UserNoNestingFragment,
  EthAccountNoNestingFragment,
  NotificationTypeNoNestingFragment,
  BatchPayloadNoNestingFragment,
} = queryFragments;

const userFragment = `
  fragment user on User {
    ...UserNoNesting
    EthAccounts{
      ...EthAccountNoNesting
    }
    NotificationTypes{
      ...NotificationTypeNoNesting
    }
  }

  ${UserNoNestingFragment}
  ${EthAccountNoNestingFragment}
  ${NotificationTypeNoNestingFragment}
`;


const usersConnection = `
  query usersConnection (
    $where: UserWhereInput
    $orderBy: UserOrderByInput
    $skip: Int
    $after: String
    $before: String
    $first: Int
    $last: Int
  ){
    objectsConnection: usersConnection (
      where: $where
      orderBy: $orderBy
      skip: $skip
      after: $after
      before: $before
      first: $first
      last: $last
    ){
      aggregate{
        count
      }
      edges{
        node{
          ...user
        }
      }
    }
  }

  ${userFragment}
`;

5.2 Единый контекст для всех компонентов


В react 16.3 появилось новое контекст-API. Его я и заюзал, чтобы в дочерних компонентах на любом уровне можно было получить доступ к единому контексту без перечисления заранее желаемых типов из контекста, а просто указывая static contextType = PrismaCmsContext и получая все прелести через this->context (включая API-клиент, схему, запросы и т.п.).

5.3 динамические фильтры


Вот это тоже очень хотелось. GraphQL позволяет строить сложные запросы с вложенной структурой. Хотелось, чтобы фильтры тоже были динамическими, формируемыми из API-схемы, и позволяли делать вложенные условия. Вот что получилось:


5.4 Конструктор сайтов


Ну и напоследок, чего мне не хватало, так это внешнего редактора сайта, то есть конструктора. Хотелось, чтобы на сервере необходимо было только минимум действий выполнять, а все конечное оформление выполнялось бы на фронте (включая настройку роутинга, формирование выборок и т.п.). Это тема для отдельной статьи, потому что помимо всего прочего я еще и написал под это свой костыльный wysiwyg-редактор на чистом contentEditable, а там очень много тонкостей. Если меня восстановят в правах и кому будет интересно, я напишу отдельную статью.

Ну а напоследок коротенькое демо-видео конструктора в действии. Пока еще совсем сырой, но мне нравится.


На том пока закончу. Много еще не написал, что хотелось бы написать, но и так много получилось. Буду рад комментариям.

P.S.: все исходники, включая исходники самого сайта, находятся здесь.

Комментарии (21)


  1. Godebug
    22.04.2019 15:22

    Хотелось найти просто комплексную CMS, написанную на javascript, использующую GraphQL и обеспечивающую сразу и бэк, и фронт. Но вот не нашел я такой.

    Плохо искали :)
    JS:https://github.com/search?l=JavaScript&o=desc&q=cms&s=stars&type=Repositories
    TS:https://github.com/search?l=TypeScript&o=desc&q=cms&s=stars&type=Repositories
    GraphQL: github.com/birkir/prime
    Но лучше бэк и фронт делать разным людям, т.к. очень много нюансов что в Express что в React. Универсальную CMS сделать очень сложно, особенно ту, что не тормозит :)


    1. Fi1osof Автор
      22.04.2019 15:24

      Нет, искал я усиленно. Но не нашел. Дайте четкую ссылку на «просто комплексную CMS, написанную на javascript, использующую GraphQL и обеспечивающую сразу и бэк, и фронт». То, что видится по вашим ссылкам, это классические API-first CMS без готового фронта.

      Но лучше бэк и фронт делать разным людям, т.к. очень много нюансов что в Express что в React. Универсальную CMS сделать очень сложно, особенно ту, что не тормозит :)

      Не спорю, нюансов очень много. И именно поэтому и хотелось, чтобы бэк отвечал и за фронт, а фронт зависел от бэка. Не жестко, но хотя бы чтобы они друг друга понимали. Вот это я и пытаюсь обеспечить.
      А на сколько тормозит или нет, можете посмотреть вживую: prisma-cms.com Конечно далеко от идеала, но вроде не особо тормознутое. А при навигации вглубь вроде вообще норм (когда уже в режиме SPA).


      1. Godebug
        22.04.2019 15:46

        Дайте четкую ссылку на «просто комплексную CMS, написанную на javascript, использующую GraphQL и обеспечивающую сразу и бэк, и фронт».

        github.com/search?l=JavaScript&q=wordpress&type=Repositories
        Все уже написано, QL конечно нет :)
        Нисколько не критикуя хотел бы заметить, что у вас много противоречий в постановке задачи. Современная разработка — это про узкую специализацию и старые подходы «все в одном» потихоньку уходят в прошлое. Соответственно, привлечь желающих к работе над ядром будет трудновато.


        1. Fi1osof Автор
          22.04.2019 15:56

          Wordpress разве был переписан на JS? *Риторический вопрос*. Я же говорил про JS. No php.

          Современная разработка — это про узкую специализацию и старые подходы «все в одном» потихоньку уходят в прошлое.

          Согласен с вами. И именно поэтому проект — это не один комплексный репозиторий, а множество отдельных компонентов. Хотите просто API? Берите любые prisma-cms модули и используете их по отдельности или совместно в рамках единого проекта. Недостаточно этих модулей? Возьмите @prisma-cms/module-boilerplate за основу и напишите свой собственный серверный модуль, который будет работать с другими prisma-cms модулями. Вот вам собственное API.
          Хотите сразу еще и фронт получить, возьмите готовую сборку сайта. Здесь уже собраны и сконфигурированы все необходимые модули и можно еще свои добавить.
          Нужен для фронта собственный новый компонент? Вот тоже есть заготовка: github.com/prisma-cms/component-boilerplate. При чем при запуске она будет работать в dev-режиме в prisma-cms окружении. А продакт будет просто как компонент для prisma-сайта.
          Конечно все это еще далеко от идеала, надо еще допиливать все и документацию писать. Но концепт такой.


          1. oller
            23.04.2019 10:55

            Не легче было дописать плагин под существующие? Просто ещё один велосипед уйдёт в века, сколько таких было…


            1. Fi1osof Автор
              23.04.2019 11:42

              Еще раз: под какие существующие? Дайте ссылку на «комплексную CMS, написанную на javascript, использующую GraphQL и обеспечивающую сразу и бэк, и фронт».
              Уже несколько раз просил это. Народ продолжает предлагать что-то, но не ясно что. Я так и не увидел то, что подходит под мои критерии, а они довольно четко поставлены.


    1. Fi1osof Автор
      22.04.2019 15:42

      К слову, почему же меня так сильно беспокоит чтобы фронт и бэк работали как-то совместно, хотя сейчас тренд все-таки разделять их. Как раз потому что, как вы и сказали, «очень много нюансов». И очень высокий темп разработки сейчас (постоянно новые версии компонентов появляются, фишки новые и т.д. и т.п.). Пересобирать проекты приходится чуть ли не каждый день (где-то баги новые, где-то фичи). И вот не хотелось бы, чтобы каждый пилил под себя фронт с нуля, а мог взять чужие готовые наработки и допиливать к ним что-то свое. А если бага в ядре где-то, то рапортавать и получать в дальнейшем обновления. И хочешь или нет, но все же фронт зависит от бэка в той или иной мере. Другой вопрос, когда это полезное взаимодействие, а когда это кандалы. Я стараюсь делать так, чтобы фронт обязательно работал именно на основе API, не зависел от серверного рендеринга и был свободен от собственных HTML-примесей (чтобы можно было без проблем свое собственное оформление прикручивать).
      На примере того же хабра: здесь фронт годами не меняется. Причины понятные: работает — не лезь. И я не говорю сейчас за то, плохо он сделан или хорошо. Я сейчас только про концепцию. Вот у меня в параллельной вкладке был выведен список комментариев (в тот момент еще один на модерации). Я ответил в другой вкладке, а в первой после этого кликнул справа стрелочки «Обновить». Вот что получилось:

      Задвоение контента


  1. MetaDone
    22.04.2019 16:14

    И два года назад (и до этого еще 8 лет) я сидел на MODX CMF (под которую тоже много своих костылей изобрел). И вот три года мы затеяли один довольно масштабный проект, под который, как мне казалось, я смогу использовать MODX. Но как оказалось, не смог…

    В итоге я решил, что надо искать что-то новое, более удобное, позволяющее как-то все это упростить. Еще раз уточню, что на тот момент я был php бэкэндщиком

    А почему не попробовали решить эту же задачу на полноценном фреймворке, например Larave/Yii/Symfony и т.п.?
    И вот каждый раз, когда под новую идею надо было добавить какую-то новую сущность, прописать/изменить поля для имеющихся, создать/удалить/изменить связи между этими сущностями (соответственно с изменением структуры базы данных), у меня в какой-то момент стало уходить по несколько часов на изменение этих сущностей. Ведь помимо того, что надо было прописать эти изменения в схеме, надо было изменить базу данных (практически вручную), актуализировать API, переписать программный код и т.д и т.п.

    Доктрина без особых усилий умеет так делать — создаете сущности, меняете в процессе их связи, поля и т.п… А миграции генерируются на основе разницы между тем что в сущностях и тем что в базе быстро и безболезненно.

    Опять же мне кажется немного странным — вроде по вашим словам больше 8 лет работы с пыхом и для решения более сложных задач логично было бы использовать инструменты опять же на пыхе, благо их сейчас на каждый случай куча написано. Почему именно переход на обертки над prisma, а не что-то на уже знакомом языке, как здесь например?


    1. Fi1osof Автор
      22.04.2019 16:30

      А почему не попробовали решить эту же задачу на полноценном фреймворке, например Larave/Yii/Symfony и т.п.?

      Скорее всего причина в том, что сначала перемены коснулись фронта (внедрение реакта). В процессе весьма утомляла задача увязывать друг с другом два отдельных языка — js и php. Из-за этого никак не оставляло чувство отделенности фронта от бэка. С полным переходом на js эта грань практически стерлась и мне настолько все это понравилось, что я полностью отказался от php. Возвращаться больше не хочу к нему.
      … Почему именно переход на обертки над prisma, а не что-то на уже знакомом языке, как здесь например?

      Причина та же: полный переход на js и отказ от php.


      1. MetaDone
        22.04.2019 16:56

        В процессе весьма утомляла задача увязывать друг с другом два отдельных языка — js и php

        Можно было бы их разделить — оставить на php только api, а фронтэнд сделать отдельным приложением.
        При наличии отдельного фронтэндщика так даже будет проще. Ну и всякие тяжелые вычисления или просто тормозные куски можно переписать на Go например, а фронтэнд об этом и не узнает.
        С другой стороны если пилить проект одному или это будет прототип то да, склеить кучку пакетов под типовую логику будет быстрее. Но значит и проект не особо большой раз его один человек тащит, в таком случае можно писать на чем угодно, лишь бы удобно было


        1. Fi1osof Автор
          22.04.2019 17:10

          Можно было бы их разделить — оставить на php только api, а фронтэнд сделать отдельным приложением.

          Это и без меня много уже кто реализовал. А мне хотелось именно чтобы все в комплексе было. Лично меня не устраивает отдельно одно и другое. Опять-таки, я не говорю, что я изобрел что-то правильное и все должны делать так. Я говорю лишь о том, что я хочу именно так, говорю почему я так хочу и что у меня получилось.

          С другой стороны если пилить проект одному или это будет прототип то да, склеить кучку пакетов под типовую логику будет быстрее. Но значит и проект не особо большой раз его один человек тащит, в таком случае можно писать на чем угодно, лишь бы удобно было

          Так уже получилось, что да, в основном я работаю один. При этом проекты не простые. И если не касаться дизайна, то все остальное делаю я. И у меня была потребность вот в таком комплексном решении. Может еще какие одиночки есть, кому это может пригодиться.


          1. MetaDone
            22.04.2019 17:35

            тогда подкину идейку — приделайте еще и что-нибудь на facebook.github.io/react-native, тогда получится полный комплект — генерим бекэнд, фронтэнд и до кучи клиентов под мобилки. Получится реально полезно если кто-то один захочет по быстрому запилить прототип чего-то


            1. Fi1osof Автор
              22.04.2019 17:56

              У меня есть небольшой опыт с react-native (одно приложение для пропускной системы). Оно на более ранней версии этой платформы, но в принципе не особо сложно запилить ее. Но честно сказать, желания нет… Вероятно, под это можно было бы даже отдельную статью написать, как я запускал свое react-native приложение. Интересный эксперимент получился. Дев-версия велась на expo.io и в целом все ОК было. Но когда я собрал прод и залил на гуглоплей, тот мне такой «а версия API минимум 26 должна быть, так что не опубликую». И в проекте expo до сих пор куча тикетов на счет старой версии API. И даже на оффсайте у них тогда говорилось, что мол мы пока не можем и не очень-то хотим подтягиваться до актуальной версии API. Итог: у меня есть приложение, но я не могу его сдать клиенту.
              Сейчас точно не скажу каким именно образом я его в итоге пересобрал (ибо приложение опубликовано 10.09.2018, подзабыл уже), но собирал я его родным Android Studio. Но там такой прикол был, что и студио не хотел просто так кушать этот проект, какие-то ему там зависимости не нравились, ибо устаревшие были. Вот и получалось: для студии expo устаревший, а для expo студия слишком новая. И получилось у меня два бранча: dev для разработки с expo (ибо с ней разработка удобней, hot reload, console debug и т.п.), и prod для сборки конечного приложения студией.
              Но был и положительный момент от перехода на студию: приложение, собранное экспой, весило 30+ метров, но что самое неприятное: на старом телефоне с android 4.4 или 4.2 (LG P500) сильно все тормозило, вот прям ооочень. Собранное же на студии приложение весит 10 метров и даже на этом старом телефоне работает вообще без тормозов.

              Но как я и сказал, двигаться в этом направлении нет желания. Слишком много танцев с бубнами. Я остановился на PWA, благо в react-scripts сейчас PWA из коробки идет.


  1. vamshop
    23.04.2019 11:19
    +1

    Очень согласен с Вашим мнением, что именно в JavaScript (а не в PHP) происходит всё самое интересное для вэба, это другая вселенная, на совсем другом уровне. А у нас по-прежнему в wordpress копаются в массе своей.

    и так же не мог найти готовое решение, движок, CMS для интернет-магазинов на JS для frontend и backend.

    Так что тоже оставлю ссылочку на github — github.com/cezerin2

    CMS для магазинов на React + MongoDB + NodeJS. Так называемое PWA приложение, api-центричное.

    Готовое решение, в смысле всё в одном: backend (api) + frontend (магазин, SSR + React) + admin dashboard (админка на чистом клиентском react, без серверного кода).

    А не как обычно, вот Вам api, а всё остальное — Ваше дело.
    Зачем мне api, если мне нужен готовый магазин, с frontend'ом для посетителей, с админкой для управления магазином.


    1. Fi1osof Автор
      23.04.2019 12:04

      Да, видел его, давно уже смотрел. К сожалению, он заточен именно под магазины. Нет, я не хочу сказать, что он плох, я хочу только сказать, что мне хотелось более универсальное решение. То есть, к примеру, я не могу на базе этого быстро запилить небольшую CRM, блог, или типа того.
      Второй момент, почему я окончательно от него отказался: API не на GraphQL. Слишком многое в запросах вшито жестко.
      Именно по этой причине я оттолкнулся от prisma.io, ибо есть возможность выбирать конечную базу данных (а можно и несколько), возможность клипать микросервисы (можно строить целые сети из призма-серверов, в которых на определенные запросы можно прописывать форвардинги запросов на другие призма-серверы) и т.д. и т.п. То есть там очень большой простор для творчества.


      1. vamshop
        23.04.2019 12:23

        Ну да, универсальность — это хорошо, но очень сложно.
        Очень сложно будет допилить проект до рабочего решения, которое будет доступно простым пользователям, а-ля wordpress.

        Но конечно всё очень круто выглядит.
        Очень важно, imho, что б всё было «user friendly», так сказать.


        1. Fi1osof Автор
          23.04.2019 12:26

          Да, никто не говорил, что это будет просто :)
          Но работа ведется давно, и есть определенные моменты, которые говорят, что скорее всего получится что-то вменяемое сделать. В следующей статье напишу подробную инструкцию по запуску сайта с нуля на базе prisma-cms. Там на самом деле особо сложного ничего нет. Будет что пощупать и уже более предметно решить на сколько это интересное или неинтересное решение.


    1. Fi1osof Автор
      23.04.2019 12:06

      Кстати, вообще про CMS на базе JS вопросов довольно много и на тостере: www.google.ru/search?q=CMS+на+JS+site%3Atoster.ru
      Но там я тоже за все это время так и не нашел четкого ответа. Один фиг все сводится к ответам типа «Возьмите это классное решение для бэка и вот это классное решение для фронта и напишите свой классный костыль для их совместной классной работы».


      1. vamshop
        23.04.2019 12:27

        Да. Тоже не понимаю этого. Нет готовых решений.
        А-ля wordpress целиком и полностью основанном на современной разработке, современных подходах, библиотеках и на современном JavaScript.

        Но всё-таки этот момент приближается, я считаю.
        Именно благодаря npm, готовым библиотекам, лёгкому встраиванию всего этого в свой проект.
        Хорошо, что уже ушли от «велосипедов» и появляется какая-то стандартизация в том числе и на уровне frontend'a.


        1. Fi1osof Автор
          23.04.2019 12:47

          Но стандарты еще только развиваются. И вряд ли они будут. Тем не менее да, унификация какая-то наблюдается. Но проблем еще куча. Могу перечислить некоторые, которые сейчас доставляют вполне определенные неудобства.

          1. SSR. До сих пор стандарта нет даже близко.

          2. Отложенная загрузка модулей. Вот появилось React. Lazy loading. Но:
          а.

          Note:
          React.lazy and Suspense is not yet available for server-side rendering. If you want to do code-splitting in a server rendered app, we recommend Loadable Components. It has a nice guide for bundle splitting with server-side rendering.

          То есть в режиме SSR это не работает. Только может к концу года реализуют.
          б. Вот так работать будет:
          const OtherComponent = React.lazy(() => import('./OtherComponent'));

          А вот так не будет:
          
          const path = './OtherComponent';
          const OtherComponent = React.lazy(() => import(path));

          Уточню вытекающую проблему: хромает динамика, не можете просто так в продакте подключить произвольный модуль, например, в цикле.
          Можно заюзать webpack dynamic import, но:
          а. Не сможете только модули-файлы проекта использовать, не сможете подключить динамически произвольный компонент из node_modules.
          б. Функция экспериментальная и очень нестабильная в продакте. В деве у меня все модули подключались, а в проде только два из 10+ появилось в списке.

          Все это ограничивает динамическое расширение конечного проекта. Пока что путь только один: переустановка модулей на сервере, пересборка и hot reload. То есть многого из того, что хотелось бы использовать и кажется вполне разумным, на самом деле на сегодня просто недоступно. Но по сравнению с двумя годами ранее ситуация действительно много лучше, а еще через два года скорее всего вообще все необходимое будет доступно.


  1. hardtop
    26.04.2019 01:32

    Прекрасная статья! Я сам был такой же. «Переписать!»… «Да там буквально ж не долго...» В итоге написал 2 CMS и бросил их. Потому что:

    • Вы одиноки. Нет документации. Нет времени её писать. Вы пишете новый код.
    • Сложно научить нового сотрудника, потому что нет документации. Код ждёт.
    • Брать новые проекты сложно, потому как нет программистов, поскольку нет документации, из-за того, что вы пишите код.


    Дело было давно. В 2008 я соскочил с PHP на Python+Django. Стало гораздо легче. Но всё равно — нет идеала, и к сожалению, так будет всегда.