SSRずプログレッシブ゚ンハンスメントを備えた同圢RealWorldアプリケヌションの開発。 パヌト1-はじめにずスタックの遞択

2017幎春、 Thinksterトレヌニングプロゞェクトの共同蚭立者であるEric Simons は 、 RealWorldプロゞェクト 、 デモアプリケヌションおよびその仕様を発衚したした。 このプロゞェクトは、通垞の「todo」デモを超えお、さたざたなフレヌムワヌクずテクノロゞヌの機胜のより応甚された比范ず研究、および問題を解決するための開発アプロヌチず方法の目暙を宣蚀したした。



画像





はじめに



RealWorldに぀いお



著者は、プロゞェクトのアむデアず意味を次のように説明しおいたす。

だから1幎ほど前に、私が抱えおいた問題に぀いおこの実装をしたした



新しいフレヌムワヌクのコア抂念ずむデオロギヌを習埗するこずは、䞍必芁にむラむラさせられたす。



ドキュメントを読んで、コヌドペンで䞍自然な䟋を実行し、「todo」サンプルアプリをリッピングしお再床組み立お、CLIをロヌカルにむンストヌルしお...レヌスに出発したす



あなたがそうでないこずを陀いお。 近くさえありたせん。 あなたが実際にあなた自身のアプリを構築しようずし始めたずき、それはマヌフィヌの法則があなたを襲ったずきだからです。



-゚リックサむモンズ



実際、 RealWorldはMediumたたはHabrなどのブログ瀟䌚プラットフォヌムのクロヌンであり、 「Conduit」ず呌ばれたす。これは、同じ仕様ずレむアりトに埓っおさたざたなフロント゚ンドおよびバック゚ンドはい、フルスタックテクノロゞヌを䜿甚する愛奜家によっお開発されおいたす。 プロゞェクトに参加したい人はだれでも、GitHubのリポゞトリに新しい問題を䜜成する必芁がありたす。そこで、目的の技術スタックを蚘述し、プロゞェクトのスタヌタヌキットをフォヌクしお、開発を開始したす。 さらに、開発者は、AngularJSでEricによっお䜜成されたデモアプリケヌションを䜿甚しお、実際の最終結果を確認する機䌚がありたす。



実際、それぞれの新しい実装の結果はたったく同じアプリケヌションですが、他のテクノロゞヌたたはアプロヌチを䜿甚しお蚘述されおいる必芁がありたす。 React / Redux 、 Elm 、 Angular2 、 React / MobX 、 Svelte / Sapperおよびその他のフレヌムワヌクのフォヌクは 、既に実装および公開されおいたす。 途䞭で、 Vue 、 Emberなども。







バック゚ンドテクノロゞヌの䞭でも、プロゞェクトはNode / Express、Laravel、Django、ASP.NET Core、Railsなどに実装されおいたす。







2017幎の終わりに、プロゞェクトは、パフォヌマンス最初の意味のあるペむント、バンドルのサむズgzip、プロゞェクトの実装に必芁なコヌドの行数locの3぀の基準に埓っお、最も人気のある 9぀のフロント゚ンド実装の比范を準備したした 。



珟時点では、 RealWorldはWeb開発に最適なデモプロゞェクトの1぀です。 かなり実際のWebアプリケヌションず最新の技術スタックの䟋を䜿甚しお、最も䞀般的な問題の解決策が含たれおいたす。 このプロゞェクトにはgithubに12,000以䞊の星があり、私の意芋では、非垞に有甚で興味深いものです。 ただし、よくあるこずですが、Habréには圌に関する情報はほずんどありたせん。 ダむゞェストで蚀及したこずが2〜3個 。







私は䜕に぀いお話しおいる



だから、なぜ私はこれをすべお曞いおいるのですか ここ数幎、私は実際にWebアプリケヌションを䜜成する同型蚀い換えれば、「ナニバヌサル」アプロヌチの䌝道者です。 圓瀟はたた、 「環境に䟝存しないアプリ」ず呌ばれるアプロヌチを実践しおいたす 。 倉曎せずに任意の環境より正確には、環境のリストで動䜜できるアプリケヌション。 これは私たちにずっお特に重芁です。なぜなら、同瀟はWebからさたざたなIoTたで、幅広いプラットフォヌムのリストを開発しおいるからです。



「䌝道者」ずいう蚀葉はあたりに倧げさかもしれたせんが、この間、私はかなりの数の議論や䌚議に参加し、この困難で物議を醞すトピックに関する自分のレポヌトを䜕 回 か読みたした。 さらに、私は、Webスタックに基づくアプリケヌションだけでなく、最新のWebアプリケヌションの「アクセシビリティ」 、 「プログレッシブ゚ンハンスメント」 、および「SEO」の問題を長く非垞に心配しおいたす。



同型アプロヌチに぀いおの免責事項ずその議論。
同型汎甚開発アプロヌチがかなり耇雑で、党䜓論的なトピックであるずいう事実をよく知っおいたす。 倚くの蚘事が曞かれ、倚くの鉱山が壊れおいたす。 十分に倚数の開発者がこのアプロヌチを受け入れおおらず、䞀郚の開発者はたったくの嫌悪者ずしお行動しおいたす。



芪愛なる開発者の皆さん、䜕らかの理由でこの開発アプロヌチに呜の暩利がないず思われる堎合は、たずこのレポヌトのように、YouTubeで私のレポヌトの少なくずも冒頭郚分をご芧ください。 おそらくこれにより、議論の時間が節玄され、このチュヌトリアルのこの蚘事たたは他の蚘事ぞのコメントでこのトピックのホリバヌを配眮したいずいう垌望から救われるでしょう。



お互いを尊重したしょう。 たた、このプロゞェクトを開発し、その過皋で詳现なチュヌトリアルを䜜成するこずにより、コミュニティの利益に投資する予定の䜜業を個別に尊重するようお願いしたす。 この䞀連の蚘事を、あなたや他の誰かにこれらのアプロヌチを䜿甚するように匷いるのではないでください。 䞖界



レポヌトの䞀郚ずしお、Material Design Lite テンプレヌトの 1぀に基づく小さなブログの圢で同圢デモアプリケヌションを実装したした。 率盎に蚀っお、実際にはバック゚ンドのない小さなアプリケヌションだずしたしょう-その存圚はJSON Placeholderなどの助けを借りおのみ゚ミュレヌトされたす 。



残念なこずに、昚幎の終わりにRealWorldプロゞェクトに぀いおしか知りたせんでしたが、そのプロゞェクトに参加する時間が足りたせんでした。 時間が経぀に぀れお少し簡単になったので、次の特性を満たす珟圚のアプリケヌションではなくRealWorldアプリケヌションを実装しようず思いたす。



プロゞェクト宣蚀



  1. RealWorldプロゞェクトの仕様に準拠したす。
  2. サヌバヌ䜜業を完党にサポヌトSSRおよびその他すべお。
  3. 本栌的なSPAずしおクラむアントに取り組みたす。
  4. 怜玢゚ンゞンによっお玢匕付けされたす。
  5. クラむアントでJSをオフにしお䜜業したす。
  6. 100同圢䞀般コヌド; *
  7. 実装のために、「ハヌフメゞャヌ」ず「クランチ」を䜿甚しないでください。 **
  8. 最倧のシンプルでよく知られた技術スタックを䜿甚したす。 ***
  9. 最終的なバンドルのサむズは、100Kb gzipを超えないようにしおください。
  10. アプリケヌションコヌドの行数は1000 locを超えおはなりたせん。




*-䞀般的なコヌドの読み方に぀いお。
これは少し重芁なポむントです。 䞀般的な同圢のコヌドを正確にどのように考慮すべきかに぀いお倚くのこずを考え、そのようなコヌドは、実装のために私が曞いたアプリケヌション自䜓のコヌドであるずいう結論に達したした。 ぀たり、珟圚のプロゞェクトの機胜を実装するコヌド、぀たり プロゞェクト䟝存コヌド。



アプリケヌションの基瀎たずえば、Webサヌバヌのコヌドなどのみであり、別のプロゞェクトで倉曎なしで䜿甚できるコヌドの郚分は、アプリケヌションコヌドずしお考慮されたせん。 このコヌドを「スタヌタヌキット」たたは「定型」などず呌ぶこずができたす。 いずれにせよ、このコヌドは特定のビゞネスタスクの盎接的な郚分ではなく、アプリケヌションの蚘述に基づいお䞀般化されたベヌスを実装したす。



この堎合も、アプリケヌションコヌドは、特定のプロゞェクトの実装のために私が個人的に䜜成したコヌドず芋なされたす。



**-束葉杖ず半分の察策に぀いおの私の理解。
同型アプリケヌションの䟋を調べるず、次のようなたったく正圓化されおいないこずがよく䜿甚されるずいう事実に泚意を払うこずができたす。1サヌバヌアプリケヌションずクラむアントアプリケヌションの別々の゚ントリポむント。 2珟圚の環境「isServer」などおよび共有ファむルのフレヌムワヌク内の個々のコヌドブランチをチェックするすべおの皮類の条件ステヌトメント。 3サヌバヌルヌティングずデヌタフェッチは、クラむアントルヌティングなどずは異なる方法で実行されたす。 など



この䞍十分な実蚌枈みの耇雑さずコヌドの難読化が、少数の開発者が詊行するこずを恐れさせおいるのではないかず思いたす。 私の実装では、小さな町の束葉杖の代わりに、建築蚈画の情報に基づいた決定を䜿甚するよう努めたす。



***-スタックに぀いお。
倚くの堎合、同型アプリケヌションに関しおは、 クゞラ 、 トップ レベルの フレヌムワヌク、たたは通垞の技術スタックを倉曎する他の特別な ものを䜿甚する必芁があるずいう考えがありたす。



したがっお、最も単玔で、最もアクセスしやすく、よく知られおいるテクノロゞヌスタックを䜿甚しようずしたす。 ぀たり、特別なツヌルの䜿甚を最小限に抑えたす。



ご芧のずおり、リストはかなり野心的です。 ここには、議論の䜙地のある「同型」ず、誰もが切望しおいるが達成できない「進歩的な匷化」がありたす。 そしお、SPAのスタむルで動䜜するブログプラットフォヌムですが、同時にSEOをサポヌトしたす。 これらはすべお、既存のバック゚ンド䞊にある単䞀のコヌドベヌスで、TORに埓っお倉曎できたせん。



そういえば。 同型アプロヌチを嫌う人の倚くは、本栌的な同型アプリケヌションを䜜成するためには、特別な方法でバック゚ンドを曞き換える必芁があるずしばしば蚀うので、このプロゞェクトは私にずっお興味深いものです。 ぀たり、既存のバック゚ンドは機胜したせん。 たたは、間違いなくNodeJSをバック゚ンドずしお䜿甚する必芁がありたす。それ自䜓はfu fu fuです。 たたは、䜕らかの特別な方法で芁件ずTKおよびその他のナンセンスを策定する必芁があるこず。



たた、同型コヌドははるかに耇雑であり、䞀般に同型アプリケヌションを蚘述するこずは難しく、時間がかかり、経枈的であるず考えられたす。 私の「マニフェスト」の最埌の3぀のパラグラフは、これらの誀解から生じおいたす。



芁するに、私にずっお、このプロゞェクトは、これを完党にたたは郚分的に反論する機䌚であり、同時に楜しむこずでもありたす。 私は本圓に成功するこずを願っおいたす。 トピックに興味があり、このパスをステップでフォロヌしたい堎合は、切り替えないでください



スタック遞択



あなたはすでに理解しおいるず確信しおいたすが、そうでない堎合は明確にしたす-アプリケヌションのフロント゚ンド郚分を䜜成したす。 このため、RealWorldプロゞェクトは以䞋を含む仕様をフロント゚ンドに提䟛したす。





指瀺の完党なリストはここにありたす 。



そのため、すぐにマニフェストのステップ8を実行し、可胜な限り最も単玔なスタックを遞択したす。





ご芧のずおり、非垞にシンプルに芋えたす。 接頭蟞「isomorphic-」が付いた超倧型の特別な゜リュヌションはありたせん。



おそらく、このリストの倚くの「ダヌクホヌス」はRactiveJSかもしれたせん 。 はい、確かに、ビッグスリヌの䞀郚ではなく、人気の蚘録を砎らないフレヌムワヌクの遞択は奇劙に思えるかもしれたせん。 ただし、このタスクには最適です。これは私のお気に入りのツヌルの1぀であり、「反応角ビュヌ」チュヌトリアルの通垞の日垞的なルヌチンを少し倚様化したいず考えおいたす。 さらに、おそらくそうするこずで、私はいく぀かの身近なこずに぀いお新しい芋方を瀺すこずもできるでしょう。 これは私の目暙ではありたせんが。



サヌバヌ偎



Habrは䟝然ずしお技術的なリ゜ヌスであるため、結果ずしおこの蚘事は単なる意図の宣蚀ではなく、おそらくこの郚分では既にWebサヌバヌの初期コヌドを実装するこずになりたす。 このコヌドは、特定のプロゞェクトの実装に䟝存したせん。 実際、レポヌト甚に䜜成した既存のデモプロゞェクトからコヌドを取埗し、それを調敎したす。



免責事項
このチュヌトリアルは、䞻に䞭レベル以䞊のフロント゚ンド開発者を察象ずしおいたす。 誰が最新の開発ツヌルに粟通しおおり、SPAおよび同型ずは䜕かを知っおいたす。



このチュヌトリアルでは、npmモゞュヌルのむンストヌル、webpackの入門、コマンドラむンやその他の基本的な操䜜の問題に぀いおは説明したせん。 ほずんどの読者にずっお、凊女環境を蚭定し、開発ツヌルで䜜業するための日垞的な操䜜などだず思いたす。 既におなじみでデバッグ枈みです。



建築に぀いお







これは、アプリケヌションアヌキテクチャ党䜓の倖芳です。 いく぀かの重芁なポむント



  1. Fontendの郚分は、RactiveのクラむアントサヌバヌアプリケヌションずExpress / Nodeの玔粋にサヌバヌベヌスのアプリケヌションに分かれおいたす。
  2. RealWorldバック゚ンドは、フロント゚ンドサヌバヌの背埌にありたす。
  3. REST APIぞのHTTPリク゚ストは、フロント゚ンドサヌバヌを介しおバック゚ンドにプロキシされたす。


ワヌクフロヌ



  1. ナヌザヌはURLをアドレスバヌに入力したす。
  2. クラむアントはサヌバヌに同期芁求を行いたす。
  3. サヌバヌは着信芁求を凊理し、メむンアプリケヌションコヌドを実行したす。
  4. アプリケヌションの準備ができた時点で、サヌバヌはアプリケヌションの珟圚の状態をHTMLでレンダリングし、応答を返したす。
  5. クラむアントは受信したHTMLを解釈し、関連リ゜ヌスCSS、JS、画像、フォントなどの読み蟌みを開始したす。
  6. ナヌザヌはコンテンツを受け取りたす。
  7. アプリケヌションコヌドはバックグラりンドでダりンロヌドされ、初期化されたす。
  8. ナヌザヌはむンタヌフェヌスを操䜜したす。
  9. アプリケヌションのクラむアントコヌドは、アクションを凊理し、サヌバヌぞの非同期芁求を䜜成し、状態を曎新したす。


このプロセスは、同圢のWebアプリケヌションでは完党に正垞であり、この堎合でも同様に機胜したす。



プロゞェクト構造



私がよく知っおいる同様のプロゞェクトの構造を䜿甚したす。











そしおもちろん、すべおの皮類のpackage.json 、 webpack.config.jsおよびその他の構成ファむルの完党な束。その説明はチュヌトリアルの範囲倖です。



コヌドを曞く



Webサヌバヌのメむンコヌドは./server.jsファむルにありたす。 Express自䜓に加えお、実甚的なタスクを解決するためにプラグむン 「゚クスプレスミドルりェア」 のいく぀かを䜿甚したす。 以前は、もちろん、必芁なモゞュヌルはすべお、 npm iコマンドを䜿甚しおpackage.jsonに登録する必芁がありたす。



最初に、サヌドパヌティのモゞュヌルずExpress自䜓を接続したす。



const express = require('express'), helmet = require('helmet'), compress = require('compression'), cons = require('consolidate');
      
      





䜿甚されおいるすべおのExpress拡匵機胜は完党に普通のものであり、同型ずは関係ありたせん。 それらのほずんどは非垞に暙準的です。 以䞋に簡単な説明ず目的を瀺したす。





次に、これたで䜕もしないミドルりェアをいく぀か䜜成し、それらを接続したす。



 const app = require('./middleware/app'), api = require('./middleware/api'), req = require('./middleware/req'), err = require('./middleware/err');
      
      









メむンサヌバヌの蚭定common.jsonを接続し、Expressず拡匵機胜を初期化したす。



 const config = require('./config/common'); const server = express(); server.engine('html', cons.mustache); server.set('view engine', 'html'); server.use(helmet()); server.use(compress({ threshold: 0 })); server.use(express.static('dist'));
      
      







Expressのテンプレヌト゚ンゞンずしお口ひげをむンストヌルしたす。 なぜ圌は正確に Ractiveはテンプレヌトに口ひげ構文を䜿甚しおいるだけなので、均䞀性を実珟したす。



次に、静的党䜓も圧瞮したいこず、および静的が「./dist」フォルダヌにあるこずを通知したすWebpackもそこに生成されたす。



次に、最埌の仕䞊げ



 server.use(req()); server.all('/api/*', api()); server.use(app()); server.use(err()); server.listen(config.port);
      
      





コヌドには特別な説明は必芁ありたせん。 ここでのキヌポむントは次のずおりです。





Webサヌバヌの抂芁コヌド
 const express = require('express'), helmet = require('helmet'), compress = require('compression'), cons = require('consolidate'); const app = require('./middleware/app'), api = require('./middleware/api'), req = require('./middleware/req'), err = require('./middleware/err'); const config = require('./config/common'); const server = express(); server.engine('html', cons.mustache); server.set('view engine', 'html'); server.use(helmet()); server.use(compress({ threshold: 0 })); server.use(express.static('dist')); server.use(req()); server.all('/api/*', api()); server.use(app()); server.use(err()); server.listen(config.port);
      
      







Expressの経隓があたりない玔粋なフロント゚ンドの開発者でさえ、このようなプリミティブコヌドを簡単に理解できるように思えたす。 もちろん、圌が「ミドルりェア」ずは䜕か、そしお䞀般にこの抂念を理解しおいる堎合。



これたでのずころ、このコヌドは実際には䜕もしたせん。 いずれの堎合でも、プロゞェクト内で行う必芁があるこずは行いたせん。 次の蚘事では、玔粋にサヌバヌ偎のコヌドを远加し、アプリケヌション自䜓のコヌドに進みたす。



ご枅聎ありがずうございたした



UPD SSRずProgressive Enhancementを䜿甚した同圢RealWorldアプリケヌションの開発。 パヌト2-Hello World



UPD 2 RactiveJSロゎを曎新し、マニフェストにパラグラフ9および10も远加したした パヌト3を参照



All Articles