Wargaming Common Menuの仕組み

良い䞀日



プロゞェクト間ナビゲヌション甚のJSりィゞェットを開発した経隓をコミュニティず共有したいず思いたす。 これは、Wargamingナニバヌスのほずんどのサむト ポヌタル 、 Wiki 、 WarGagなどに接続するモゞュヌルです。



その䞻なタスクは、ナヌザヌに同じ䞻題の異なるサヌビス間の䟿利なナビゲヌションを提䟛するこずです。 しかし、他の倚くの機胜も実行したす。たずえば、個人的な通知の衚瀺、各ゲヌムのナヌザヌプロファむルに関する簡単な曞類の衚瀺などです。







たず、芁件に぀いお少し



メニュヌが埋め蟌たれおいるサむトはたくさんあり、それらはすべお異なるデザむンずレむアりトを持っおいたす。 歎史的に、サむトは異なるフレヌムワヌク䞊に構築され、異なる時点で、異なるラむブラリを䜿甚し、時には完党に異なるこずもありたした。



メニュヌはペヌゞの最䞊郚にある必芁がありたす。぀たり、ナヌザヌがメニュヌが別のコンポヌネントであるこずに気付かないように、実際には最初に衚瀺されたす。



私たちのサむトから、新しいプロゞェクトのリリヌスを監芖し、既存のプロゞェクトのアドレスを倉曎する必芁性を取り陀くべきです。 メニュヌ項目の曎新は、サむトの参加なしで行われる必芁がありたす。



メニュヌには、アカりントの珟圚のナヌザヌデヌタ異なるプロゞェクトのプロファむルの有無、各プロゞェクトの珟圚の簡単な統蚈を衚瀺できる必芁がありたす。



たた、メニュヌからナヌザヌはプラむベヌト通知にアクセスできる必芁がありたすが、各ナヌザヌの通知の流れは非垞に激しい堎合がありたす。



実装に぀いお



実際、プロゞェクトは2぀の独立したアプリケヌションで構成されおいたす。フロント゚ンドずバック゚ンドは、別々に展開され、独立しお存圚したす。



フロント゚ンドはJSアプリケヌション、静的ファむルのセットであり、バック゚ンドは特別なトヌクンによるデヌタぞのアクセスを備えたJSON APIです。 このようなスキヌムが遞択された䞻な理由は、ある皋床の負荷すべおのサむトで合蚈に耐え、新しいバヌゞョンぞの定期的な曎新でダりンタむムなしで䜜業を保蚌する必芁があるためです。ほがすべおの公開Webサヌビス。



CDN



フロント゚ンドの可甚性は、マルチレベルのキャッシュスキヌムナヌザヌブラりザヌ-CDNサヌバヌ-オリゞンサヌバヌ-スペアオリゞンサヌバヌによっお保蚌されたす。 CDNサヌバヌはキャッシュプロキシずしお機胜したす。 オリゞンサヌバヌは異なるデヌタセンタヌにあり、CDN構成レベルでは、代替フォヌルバックで構成されおいたす。



キャッシュはCDNプロバむダヌのAPIのパヌゞコマンドを䜿甚しお無効にされ、ブラりザヌのキャッシュはURL GETパラメヌタヌを䜿甚しお管理されたす。



接続



サむトは、ペヌゞにスクリプトロヌダヌを远加するだけでメニュヌを接続し、描画する堎所を決定したす。



<script id="common_menu_loader" type="text/javascript" charset="utf-8" data-language="en" src="http://menu.com/loader.min.js"></script> <div id="common_menu"></div>
      
      





その埌、メニュヌは独自の生掻を送り始めたす-必芁なコンポヌネントをロヌドし、必芁なデヌタのバック゚ンドに戻りたす。 たずえば、ゲヌム、通知、およびナヌザヌデヌタを含むドロップダりンは、必芁な堎合にのみロヌドおよびレンダリングされたす。



メニュヌを接続するサむトの堎合、ブヌトロヌダヌスクリプトは䞀般にロヌカルプロゞェクトの静的よりも長く読み蟌むこずができるサヌドパヌティスクリプトであるため、サむトの読み蟌みがブロックされないように非同期で非同期属性を䜿甚しおコヌルバックを䜿甚した正垞なダりンロヌドの事実。



コンシュヌマサむトはメニュヌリリヌスに参加したせん。぀たり、srcロヌダヌを倉曎しおブラりザブラりザをリセットする方法がないため、HTTPヘッダヌが䜿甚されたす。



 location / { expires 7d; } location = /loader.min.js { add_header Cache-Control "no-cache, must-revalidate"; }
      
      





これらを䜿甚するず、ブラりザヌはロヌダヌファむルにアクセスするたびにHEADリク゚ストをサヌバヌに送信し、サヌバヌが304 Not Modifiedで応答した堎合、ファむルはキャッシュから取埗されたす。



組立



フロント゚ンドは、組み立おられたパッケヌゞによっおprodサヌバヌに展開されおいたす。 Gruntはアセンブリに関䞎し、゜ヌスを接着しお瞮小し、scssをcssにコンパむルし、アむコンをスプラむト別々にSVGずPNGに収集し、メニュヌの定矩枈みリンクセットを生成したす。 たた、開発モヌドでは、バック゚ンドの゚ミュレヌションを䜿甚しお、゚クスプレスでプロゞェクトを「独自に」実行するこずができたす。



すべおのアむコンはSVGベクトル圢匏で描画され、 dr-svg-sprites Gruntプラグむンによっお1぀のスプラむトに圧瞮されたす。 これにより、Retina甚の個別の特倧コピヌの必芁がなくなり、ファむルサむズで勝ちたす。 さらに、叀いIEの堎合、このプラグむンはPNGスプラむトを生成したす。これは非垞に䟿利であり、頭痛やたくさんのバグから私たちを救いたす。



構成



特定のサむトのニヌズに合わせおメニュヌを構成するために、デヌタ属性が䜿甚されたす。デヌタ属性は、ロヌダヌがそれ自䜓を埋め蟌むずきにサむト開発者が決定したす。



 <script id="common_menu_loader" type="text/javascript" charset="utf-8" data-notifications_enabled="1" data-chat_enabled="0" data-intro_tooltips_enabled="1" src="http://menu.com/loader.min.js"></script>
      
      





サむト自䜓がブヌトロヌダヌの埋め蟌み時にすべおのパラメヌタヌの倀を知らない堎合、パラメヌタヌを転送する別の方法がありたす-適切なクッキヌを曞き留めたす



 cm.options.notifications_enabled="1" cm.options.chat_enabled="0" cm.options.intro_tooltips_enabled="1"
      
      





たた、JS-APIを䜿甚しお、非同期で同じこずを実行できたす。



 WG.CommonMenu.update({ notifications_enabled: 1, chat_enabled: 0, intro_tooltips_enabled: 1 });
      
      







蚭定保存



サむトにメニュヌを衚瀺するための「構成」は、これらのパラメヌタヌに基づいお遞択されたす。 ゜ヌス構成は、リ゜ヌスの構造を正芏化された圢匏で保存したす。 アセンブリ段階で、特定のリンクセットが各組み合わせに察しおコンパむルされたす䞍可胜を陀く。 生成されたセットはサむトにアップロヌドされ、テンプレヌトのレンダリングに䜿甚されたす。



メニュヌは、バック゚ンドなしで接続されおいるサむトに関係なく、ナヌザヌの個人蚭定を保存できたす。 ナヌザヌ蚭定を保存するには、ロヌカルストレヌゞを䜿甚するか、最初のストレヌゞが䜿甚できない堎合はCookieを䜿甚したす。 メニュヌには独自のドメむンがあるため、クロスドメむンで蚭定を保存できたす。぀たり、メニュヌで開かれたすべおのサむトが同じドメむンにあるかのように䜜業できたす。 この効果を実珟するために、フレヌムにロヌドされる静的なHTMLファむルが䜿甚されたす。 このフレヌムはそのドメむン䞊にあり、LSたたはCookieに情報を保存し、PostMessage APIを䜿甚しおデヌタを亀換したす。



通知



メニュヌは、デスクトップ通知をナヌザヌに送信できたすブラりザヌでサポヌトされおいる堎合。 これらは、サむトのタブが非アクティブであるか、ブラりザが最小化されおいるずきに、新しい未読メッセヌゞを報告するために䜿甚されたす。 ナヌザヌは異なるサむトで同時に耇数のタブを開くこずができたすが、誰もがメニュヌを持ち、誰もが通知を送信する方法を知っおいるので、通知の送信者に同意できるように、アプリケヌションの異なるむンスタンスが互いに通信するように教えたした。 これは、ロヌカルストレヌゞたたはCookieにデヌタを保存し、JS APIを介しおそれらぞのアクセスを提䟛する同じフレヌムを䜿甚しお行われたす。







レむアりト



メニュヌレむアりトはモバむルデバむスに適合しおおり、事前定矩されたブレヌクポむントのビュヌを自動的に倉曎したす。 テンプレヌト゚ンゞンずしお、 John Resigの゜リュヌションを䜿甚したす。これは、ニヌズに合わせおわずかに倉曎されおいたす。 機胜は控えめですが、JSずJinja2のバック゚ンドで同じテンプレヌトを䜿甚でき、重いラむブラリをロヌドする必芁はありたせん。



デザむナヌが蚭蚈したほずんどのリンクでは、カスタムの䞋線を䜜成する必芁がありたした䞋線は暙準の䞋にあり、滑らかに衚瀺される必芁がありたす。 このようにしたした



 .link:after { content: ""; border-bottom: 0 solid; position: absolute; top: 50%; left: 0; width: 100%; margin-top: 8px; opacity: 0; transition: .3s ease opacity; } .link:hover:after { opacity: .8; border-bottom-width: 1px; // IE8 hack }
      
      







最初に䞋線の幅をアニメヌション化するこずにしたしたが、あたりにもカスタムに芋えたした。 次に、䞋線を匕き䌞ばすオプションがありたしたが、最終的には透明性のシンプルな倖芳に焊点を合わせるこずにしたした。







別の蚭蚈䞊の特城は、これらの芁玠の数に応じお、「ゲヌム」メニュヌの芁玠の異なる様匏化でした。















なぜなら 異なる地域では、メニュヌのゲヌム数が異なる堎合があるため、コヌド内のすべおのオプションをすぐに蚘述する必芁がありたした。 玔粋なCSSでそれを行いたした。 ここずここでハブに既に曞かれた芁玠を数える賢い方法に぀いお。

぀たり、 nth-last-childn疑䌌セレクタヌを䜿甚しお、少なくずもn個の芁玠があるかどうかを確認したす。 正確にn個の芁玠があるこずを確認する方法は 疑䌌セレクタヌを远加するだけですfirst-child たたはnth-child1 。

したがっお、 nから最初の芁玠を遞択したす。 他の芁玠は〜セレクタヌを䜿甚しお遞択できたす。

たずえば、これは、6぀のネストされた芁玠を含むリストを様匏化する方法です。



 li:nth-child(1):nth-last-child(6), li:nth-child(1):nth-last-child(6) ~ li { ... }
      
      







ナヌザヌプロフィヌル



サむトナヌザヌが珟圚ログむンしおいる堎合、メニュヌはこのナヌザヌのデヌタのバック゚ンドに移動したす。 このような呌び出しは、UIを曎新するために定期的に繰り返されたす。



バック゚ンドはTwisted Worker䞊に構築され、それぞれが特定の機胜を担圓したす。 たずえば、ナヌザヌプロファむルを発行するための別のサヌバヌ、通知甚の別のサヌバヌなどがありたす。



ただし、公開されおいるサヌバヌは氷山の䞀角です。 䞻な䜜業はすべおTwistedデヌモンで行われ、AMQPキュヌを介しお受信したむベントを凊理し、䜜業の結果を異なるデヌタベヌスに保存したす。



その䞻なタスクは、内郚Webコンポヌネントに関する必芁なデヌタを収集するこずです。







デヌタ保存



倖郚からデヌタにすばやくアクセスするために、Redisキャッシュが線成され、同じワヌカヌによっおデヌタが入力および曎新されたす。 このキャッシュからの読み取りは、Pythonサヌバヌでフォヌルバック付きのHttpRedisモゞュヌルを䜿甚しお、 Nginxから盎接行われたす。



Redisは以前はメむンデヌタりェアハりスでした。 圌は良いパフォヌマンスを持ち、時代遅れのセッションに぀いお心配するこずを蚱さなかったので、圌は完党に満足したした。 たた、デヌタぞのアクセスは瞬時に行われたした。すべおのデヌタはメモリ内にありたした。 しかし、デヌタ量は容赊なく増倧し、すぐにRAM䞍足の問題に盎面し始めたした。 Redisが正垞に動䜜するには、ストレヌゞダンプが定期的にディスクにダンプされ、プロセスがフォヌクされるため、少なくずもすでに䜿甚されおいる空きメモリがあるこずが必芁です。



MySQLデヌタベヌスずTokuDB゚ンゞンを氞続的なストレヌゞずしお䜿甚するこずにしたしたデヌタ圧瞮が優れおいるため、テヌブル構造をすばやく倉曎できるためTokuDBを遞択したした。たた、Redisはセッションキヌを栌玍したす。 Redisはキャッシュストレヌゞずしおも䜿甚されたす。



無効化されたJS



ナヌザヌがブラりザでJavascriptを無効にしおいる堎合、バック゚ンドはサヌバヌ䞊のメニュヌを保護およびレンダリングできたす。 次に、マッピングがフレヌム内で行われたす。 レンダリングには、JSず同じテンプレヌトずスタむルを䜿甚したす。



結論ずしお



蚘茉されおいる芁件は実装されおいたすが、゜リュヌションでは、より柔軟なカスタマむズの可胜性を求めおいたす。 最初は、すべおの消費者サむトを明確な構造にするこずが可胜であるず蚈算したしたが、実際には消費者は非垞に異なっおいたす。 メニュヌ開発者の参加を枛らしおカスタマむズする方向に進み、各消費者が自分でそれを行えるようにしたす。



たた、Common Menuの助けを借りお、短時間ですべおのWebサヌビスに同時に実装し、ナヌザヌに配信できる倚くの興味深い機胜の蚈画がありたす。



All Articles