ヘッドレスCMS。 なぜ私が曞いおいるの

みなさんこんにちは



この最近の蚘事は、私にこの出版物を曞くよう促したした昚日芋たした。



Headless / content-first / api-firstなどの䞻な機胜をもう䞀床説明しおください。 私はCMSではありたせん。玠材は充実しおおり、おそらく倚くの人がすでにこの傟向に粟通しおいたす。 そしお、システムを䜜成する理由ず方法、既存のシステムから遞択できなかった理由、以前に遭遇した他のシステムに぀いお考えおいるこず、これらすべおに぀いおどのような芋通しがあるかに぀いおお話したいず思いたす。 フィクションは膚倧な量になりたすが2幎間でこの資料に぀いお、より面癜く有甚なものを曞きたす。 猫の䞋で誰が気にしおください。



䞀般的に、物語は本圓に長く、私は最初にそれを話そうずしたす。 この゚ンゞンを自分で䜜成する本圓の理由をもっず明確にするため、たたは単にこれがないず、なぜ私がこのようにやっおいるのかを地䞊で説明するのが難しくなりたす。



しかし、初心者のために、それにもかかわらず、私は自分のために珟代のヘッドレスCMSの䞻芁な遞択基準を簡単に曞き留めたす。 人々が倚くのブナを読むために途切れず、最終的に䜕が䌝えられるのか理解しおいないように。



芁するに、私はすべおを1か所に眮きたいず思っおいたした。背面ず前面の䞡方そしお、どちらでもない、GraphQL-API、そしお「Make Beautiful」ボタンなど、デヌタベヌスを管理するこずです。 これは芋぀かりたせんでした。 私自身もただこれをやっおいたせんが、党䜓ずしおは非垞に倚くのこずが刀明したした。そしお最も重芁なこずは、実際のプロゞェクトを行うこずができるこずです。



したがっお、私のアプロヌチは科孊的で正圓化されるずはほずんど蚀えたせん。 事実、私は䞀般的に自分の䜕かを曞くこずが非垞に倚いです。 ここでプログラムするのが奜きです。 そしお2幎前そしおその8幎前に私はMODX CMFに座っおいたしたその䞋で倚くの束葉杖も発明したした。 そしお3幎間、かなり倧芏暡なプロゞェクトを開始したしたが、その䞋でMODXを䜿甚できるように思えたした。 しかし、結局のずころ、私はできたせんでした...䞻な理由は、技術的な芁件のないスタヌトアップであり、毎日そしお1日に数回倉化し、補足される倚くのアむデアがあったこずです。 そしお今、新しいアむデアの䞋で、新しい゚ンティティを远加し、既存の゚ンティティのフィヌルドを登録/倉曎し、これらの゚ンティティ間の関係を䜜成/削陀/倉曎する必芁があるたびにそれぞれ、デヌタベヌス構造の倉曎に䌎い、ある時点でこれらの゚ンティティを倉曎するのに数時間かかりたした。 実際、これらの倉曎をスキヌムに登録する必芁があるずいう事実に加えお、デヌタベヌスの倉曎ほが手動、APIの曎新、プログラムコヌドの曞き換えなどが必芁でした。 したがっお、このすべおの䞋で前線を曎新する必芁がありたした。 その結果、私は新しい、より䟿利なものを探す必芁があるず刀断したした。 そのずき、私はphpバック゚ンドだったこずをもう䞀床明確にしたす。そのため、さたざたなフロント゚ンドビルダヌ、少ないプロセッサ、npmなどを発芋し始めたこずに驚かないでください。 など しかし、ずにかく、私たちのプロゞェクトでは埐々に、react + less、GraphQLのAPI、およびexpressのサヌバヌに前線が珟れたした。



しかし、すべおが今のようにバラ色であるずは限りたせん。 これは2幎以䞊前であるこずを思い出させおください。 最新のJS Webに2幎未満しかアクセスしおいない堎合は、次の蚘事を読むこずをお勧めしたす 。CreateReact アプリ habr を䜿甚するN個の理由 。 簡単に蚀うず、反応スクリプトの出珟により、webpackの構成などに煩わされるこずはありたせん。 これはすべおバックグラりンドに入りたす。 芪切な人はすでにwebpackを蚭定しおいるので、ほずんどの反応プロゞェクトはほずんど動䜜するこずが保蚌されおおり、最終開発者は䟝存関係やロヌダヌなどを蚭定するのではなく、最終補品のプログラミングに盎接集䞭しおいたす。 しかし、これは埌です。 そしおその前に、私はこのりェブパックを蚭定し、远い぀くために圌ず䞀緒に飛んだすべおの束の曎新に埓う必芁がありたした。 など しかし、これは䜜業の䞀郚にすぎず、本質的には前線にすぎたせん。 たた、サヌバヌも必芁です。 たた、APIも必芁です。 たた、SSRサヌバヌ偎レンダリングも必芁です。私が知る限り、反応スクリプトはただ提䟛しおいたせん。 䞀般に、すべおは今よりもはるかに耇雑で、それほど倚くはありたせんでした。 そしお、どうやっお私は束葉杖を぀けたしたか...



想像しおみおください





その結果、これたで、これの最初のバヌゞョンの1぀には、500人以䞊の出垭者がいるプロゞェクトがあり、シヌズン冬には1日あたり1000〜1700人のナニヌクな孊生がいたす。 皌働時間2か月。 これは、予防的な゜フトりェアの曎新埌にサヌバヌを手動で再起動したためです。 この再起動前には、皌働時間はさらに6か月以䞊でした。 しかし、最も興味深いのはメモリ消費です。 珟圚、ほが700メガバむトのjsプロセスがありたす。 はい、はい、私もここであなたず笑っおいたす:)もちろん、これはたくさんありたす。 そしおその前に、私はもう少し予防し、この指暙を改善したした。 以前は、プロセスごずに合蚈1000M +がありたした...それにもかかわらず、それは機胜し、かなり蚱容できたした。 たた、11月にGoogleがPageSpeed Insightsアルゎリズムを倉曎する前は、サむトのパフォヌマンスメトリックは97/100でした。 蚌明



このプロゞェクトなしでさらに開発されたシステムに基づいた、このプロゞェクトに基づく䞭間結論プロゞェクトは取り残されたした



長所



  1. GraphQLを䜿甚するこずでプロゞェクトAPIがより柔軟になり、サヌバヌリク゚ストの数が倧幅に削枛されたした。
  2. プロゞェクトは、npm䞊の膚倧な数のコンポヌネントにアクセスできたす。
  3. 䟝存関係やgitなどを䜿甚するこずで、プロゞェクト管理がより透明になりたした。
  4. 結果ずしおこの動物園から䜕を削陀できるかわからない堎合そしお、1぀のサむトで耇数のバヌゞョンのバグを芋るこずは珍しくありたせん、構築されたスクリプトずスタむルは、叀いサむトの䞀連の個別のスクリプトよりも確かに楜しいです。
  5. サむトはよりむンタラクティブになり、ペヌゞは再起動せずに機胜したす。以前に衚瀺したペヌゞに戻るためにサヌバヌを繰り返し呌び出す必芁はありたせん。
  6. デヌタ線集は、ペヌゞ䞊で盎接実行されたす。「衚瀺するものず衚瀺するものを線集する」ずいう原則に基づき、個別の管理パネルはありたせん。


短所䞻に開発者向け



  1. すべおが非垞に耇雑です。 本圓に。 䞀郚のサヌドパヌティ開発者のプロゞェクトぞの接続は、単玔に非珟実的です。 私はそれが䜕をどのように機胜し、私の足がどこから成長するかをほずんど理解しおいなかった。 透明性に぀いお蚀及されおいるプラ​​スの3ペヌゞを芋るず、透明性はどこかにフックするず、壊れおいるものをすぐに芋るこずができたすスクリプトは構築されたせんが、コミットず差分によっおあなたはそれが匕っかかった堎所を芋぀けるこずができたす。 たあ、䜕か新しいものを远加するこずができ、それが機胜する堎合、少なくずも、はい、すべおがうたく飛んだこずを明確に理解しおいたす。 しかし、党䜓的にはただ地獄のような地獄です。
  2. キャッシングの難しさ。 その埌、私は自分のためにアポロクラむアントを発芋したした。 そしおその前に、私が蚀ったように、フラックスベヌスのストレヌゞを曞きたした。 これらのストレヌゞにより、さたざたなコンポヌネントからレンダリングに必芁なデヌタを取埗できたしたが、クラむアント偎のキャッシュサむズは非垞に倧きかった゚ンティティの各セットには独自のリポゞトリがありたした。 その結果、オブゞェクトが以前にリク゚ストされたかどうか぀たり、それを芋぀けるためにサヌバヌにリク゚ストする䟡倀があるかどうか、関連するすべおのデヌタが利甚可胜かどうかなどを怜蚌するこずは困難でした。
  3. スキヌマ、デヌタベヌス構造、リゟルバの問題デヌタを受信/倉曎するためのAPI機胜。 私が蚀ったように、私は手動で回路を曞き、リゟルバも曞きたした。 リゟルバで䜕をするかで、キャッシュを提䟛し、ネストされたリク゚ストやその他の埮劙な凊理を提䟛しようずしたした。 その瞬間、私は本質ずGraphQLプログラムコヌドに深く入り蟌たなければなりたせんでした。 利点は、GraphQLの仕組み、その長所ず短所、およびそれをよりよく調理する方法を䞀般的によく理解しおいるこずです。 欠点は、もちろん、アポロのようなコマンドで曞かれたアメニティやバンをすべお1぀に曞くこずができないこずです。 その結果、私がアポロを発芋したずき、もちろん、私はそれらのコンポヌネントを非垞に喜んで䜿い始めたしたしかし、䞻に前面で、以䞋にその理由を説明したす。


䞀般的に、時代遅れのテクノロゞヌを䜿甚するこのプロゞェクトは、個人的には100のものであるため、より良い時期たでそれを攟棄する䜙裕がありたす。 しかし、さらに進んでプラットフォヌムを開発する必芁があった他のプロゞェクトがありたす。 そしお数回、すべおをれロから曞き盎さなければなりたせんでした。 さらに、遭遇した個々のタスクず、その結果ずしお開発および適甚した゜リュヌションに぀いお詳しく説明したす。



スキヌマファヌスト。 最初に回路、次に他のすべお



サむトWebむンタヌフェむス、シンクラむアントなどはすべお情報の衚瀺です蚱可されおいる堎合は情報管理、および蚱可されおいる堎合は機胜が蚱可されたす。 しかし、最初に、すべお同じ、デヌタベヌステヌブル、列など。 途䞭でデヌタベヌスを操䜜するためのいく぀かの異なるアプロヌチに遭遇したので、私はスキヌマファヌストのアプロヌチが最も奜きでした。 ぀たり、゚ンティティずデヌタ型のスキヌマを手動たたはむンタヌフェむスを介しお蚘述し、スキヌマを展開し、蚘述された倉曎をデヌタベヌスにすぐに適甚したすテヌブル/列が䜜成/削陀され、それらの間の関係も。 実装に応じお、このデヌタを管理するために必芁なすべおのリゟルバヌ関数も生成したす。 䜕よりもこの方向で、私はprisma.ioプロゞェクトが奜きでした。



あなたの蚱可を埗お、私はハブに぀いおもプリズムに぀いおの蚘事を芋たこずがないので、私は圌らに少し泚意を匕きたす。プロゞェクトは本圓に非垞に興味深いからです。そしお、圌らなしでは、私をそんなに喜ばせるようなプラットフォヌムはありたせん。 実際、prisma.ioが非垞に倧きな圹割を果たしおいるため、プラットフォヌムをprisma-cmsず呌んでいたす。



実際、prisma.ioはSaaSプロゞェクトですが、倧きな譊告がありたす。圌らは、行うこずのほずんどすべおをgithubに配眮したす。 ぀たり、非垞にリヌズナブルな料金でサヌバヌを䜿甚する数分で独自のデヌタベヌスずAPIを構成するこずも、自宅ですべおを完党に展開するこずもできたす。 この堎合、プリズムは論理的に2぀の重芁な別個の郚分に分割する必芁がありたす。



  1. Prisma-server、぀たりデヌタベヌスも回転しおいるサヌバヌ。
  2. プリズマクラむアント。 基本的にはサヌバヌでもありたすが、デヌタ゜ヌスprisma-serverに関しおはクラむアントです。


次に、この玛らわしい状況に぀いお説明したす。 䞀般に、プリズムの本質は、単䞀のAPI゚ンドポむントを䜿甚しお、さたざたなデヌタ゜ヌスを操䜜できるこずです。 はい、ここでは誰もがGraphQLを思い぀いたず蚀うでしょう。prismaはここでは必芁ありたせん。 䞀般的に、誰もが正しいでしょうが、重倧なポむントがありたすGraphQLは原則ず党䜓的な䜜業のみを定矩したすが、それ自䜓では最終的なデヌタ゜ヌスを䜿甚した䜜業を提䟛したせん。 圌は、「ナヌザヌが送信できるリク゚ストを蚘述するAPIを䜜成できたすが、これらのリク゚ストをどのように凊理するかはナヌザヌが決める必芁がありたす。」 そしおもちろん、プリズムもGraphQLを䜿甚したすちなみに、さたざたなアポロ補品を含む他の倚くのもの。 しかし、これに加えおプリズムは、デヌタベヌスでの䜜業を提䟛するだけです。 ぀たり、スキヌムずそのデプロむメントに぀いお説明するず、必芁なテヌブルず列およびそれらの間の関係が指定されたデヌタベヌスにすぐに䜜成され、必芁なすべおのCRUD関数もすぐに生成されたす。 ぀たり、プリズムを䜿甚するず、GraphQLサヌバヌだけでなく、すぐにデヌタベヌスを操䜜できる完党に機胜するAPIを取埗できたす。 したがっお、Prisma-serverはデヌタベヌスずデヌタベヌスずの盞互䜜甚を提䟛し、prisma-clientを䜿甚するず、リゟルバヌを蚘述し、prisma-serverたたはいく぀かのprisma-サヌバヌでもにリク゚ストを送信できたす。 したがっお、prisma-clientは自分でしかデプロむできないそしおSaaS prisma.ioがprisma-serverずしお䜿甚されるこずができ、prisma-serverを自分でデプロむでき、通垞はプリズムにたったく䟝存せず、それがすべおですあなたのもの。



ここでは、プラットフォヌムの基瀎ずしお、プリズムを自分甚に遞択したした。 しかし、それから完党なプラットフォヌムを埗るために自分でそれをスピンしなければなりたせんでした。



1.スキヌムのマヌゞ



圓時、プリズムは回路を組み合わせるこずができたせんでした。 ぀たり、タスクは次のずおりです。



1぀のモゞュヌルに蚘述されたナヌザヌモデルがある



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





そしお別のモゞュヌルで



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





1぀のプロゞェクトの䞀郚ずしお、これら2぀のスキヌムを自動的に組み合わせお出力を取埗したす。



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





しかし、その埌、このプリズムはできたせんでした。 merge-graphql-schemasラむブラリを䜿甚しおこれを実装するこずが刀明したした。



任意のプリズムサヌバヌで動䜜したす。



プリズムでは、構成は特別な構成ファむルに曞き蟌たれたす。 䜿甚されおいるプリズムサヌバヌのアドレスを倉曎する堎合は、ファむルを線集する必芁がありたす。 些现なこずで、快適ではありたせん。 たずえば、endpoint = http// endpoint-address yarn deployyarn startのように、コマンドでURLを指定できるようにしたした。 これは数日間殺されたした...しかし、今では、1぀のプリズムプロゞェクトを任意の数の゚ンドポむントに䜿甚できたす。 ずころで、prisma-cmsはロヌカルデヌタベヌスでも、SaaSプリズムサヌバヌでも簡単に機胜したす。



モゞュヌル/プラグむン



これは䞀般に十分ではありたせんでした。 私が蚀ったように、プリズムの䞻なタスクは、さたざたなデヌタベヌスで䜜業を提䟛するこずです。 そしお、圌らはこれに぀いお玠晎らしい仕事をしおいたす。 既に、MySQL、PostgreSQL、Amazon RDS、MongoDB、さらにいく぀かの皮類の゜ヌスの䜿甚をサポヌトしおいたす。 ただし、モゞュヌル匏むンフラストラクチャは提䟛したせん。 これたでのずころ、垂堎などはありたせん。 兞型的なブランクはごくわずかです。 ただし、耇数のブランクから2぀たたは3぀を遞択しお、1぀のプロゞェクトにむンストヌルするこずはできたせん。 いずれかを遞択する必芁がありたす。 最終プロゞェクトに異なる数のモゞュヌルをむンストヌルできるようにし、回路ずリゟルバヌを展開するずきに、機胜をすべお備えたこのような単䞀のプロゞェクトが楜しくなるようにしたかったのです。 たた、グラフィカルむンタヌフェむスはただありたせんが、最終プロゞェクトで組み合わせるこずができる20以䞊の䜜業モゞュヌルずコンポヌネントが既にありたす。 ここで個人的な定矩に぀いお少し決定したす。モゞュヌルは背面にむンストヌルされるものデヌタベヌスずAPIを拡匵するであり、コンポヌネントは前面にむンストヌルされるものさたざたなむンタヌフェヌス芁玠を远加するためです。 これたでのずころ、モゞュヌルを接続するためのグラフィカルむンタヌフェむスはありたせんが、この方法で曞くこずは難しくありたせんこれはよく行われたせん。



  constructor(options = {}) { super(options); this.mergeModules([ LogModule, MailModule, UploadModule, SocietyModule, EthereumModule, WebrtcModule, UserModule, RouterModule, ]); }
      
      





新しいモゞュヌルを远加した埌、単に1぀のコマンドでデプロむを実行するだけで十分です。ここでは、新しいテヌブル/列ず拡匵機胜が既にありたす。



5バック゚ンドの倉曎に察応するフロント



これはたったく十分ではありたせんでした。 これに䜙談がありたす。 実際のずころ、私が芋たすべおのAPIファヌストCMSは、「APIを提䟛するのは玠晎らしいこずであり、あなたは最前線に望むものを台無しにしおしたう」ずいうこずです。 これは圌らの「あなたが望むものは䜕でもねじ」であり、実際、「あなたが望むように仲間」を意味したす。 UIフレヌムワヌクが蚀うのずたったく同じで、「クヌルなボタンを芋お、それをすべお実行し、自分自身でバック゚ンドず混同したす」ず蚀いたす。 それは垞に殺された。 GraphQLを䜿甚し、前埌の䞡方を提䟛する、javascriptで蚘述された包括的なCMSを芋぀けたいだけです。 しかし、私はそのようなものを芋぀けたせんでした。 APIの倉曎がすぐにフロントで認識されるようにしたかったのです。 このため、いく぀かのサブステップが完了したした。



5.1 APIフラグメントの生成



前面では、スキヌマファむルのフラグメントがリク゚ストに登録されたす。 サヌバヌ䞊でAPIが再構築されるず、APIフラグメントを含む新しいJSファむルも生成されたす。 そしお、リク゚ストでは次のように曞かれおいたす



 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すべおのコンポヌネントに1぀のコンテキスト



React 16.3では、 新しいコンテキストAPIが導入されおいたす 。 任意のレベルの子コンポヌネントで、コンテキストから事前に必芁なタむプをリストせずに単䞀のコンテキストにアクセスできるようにしたしたが、単に静的contextType = PrismaCmsContextを指定し、this->コンテキストAPIクラむアント、スキヌムを含む 、リク゚ストなど。



5.3動的フィルタヌ



私も本圓にやりたかった。 GraphQLを䜿甚するず、ネストされた構造を持぀耇雑なク゚リを䜜成できたす。 フィルタヌも動的で、APIスキヌムから圢成され、ネストされた条件を䜜成できるようにしたかったのです。 起こったこずは次のずおりです。





5.4りェブサむトビルダヌ



そしお最埌に、私が欠けおいたのは倖郚サむト線集者、぀たりデザむナヌでした。 サヌバヌ䞊で最小限のアクションのみを実行したかったため、最終的な蚭蚈はすべおフロントで行う必芁がありたすルヌティングの蚭定、遞択の生成など。 これは別の蚘事のトピックです。䜕よりも、玔粋なcontentEditableで、私はそれのために私のwrutch wysiwyg゚ディタヌも曞いたので、倚くの埮劙な点がありたす。 自分の暩利が回埩し、興味のある人がいる堎合は、別の蚘事を曞きたす。



さお、最埌に、動䜜䞭のデザむナヌの短いデモビデオ。 ただ生ですが、私はそれが奜きです。





それが終わるたで。 曞きたいこずはただ曞いおいたせんが、たくさんのこずが起こりたした。 コメントさせおいただきたす。



PSサむト自䜓の゜ヌスコヌドを含むすべおの゜ヌスコヌドはこちらです。



All Articles