スケヌラブルなTypeScriptアプリケヌションの構築。 パヌト1-モゞュヌルの非同期読み蟌み

この蚘事のアむデアは、オフィスで30床の厳しい仕事をし、「最新のWebアプリケヌションをどのように構築する必芁があるか」ずいうトピックに関する深い反省ずホリバヌを経お生たれたした。



そしお、アむデアは、Habréのタスクに取り組む私のプロセスを述べるために私に来たした。 そしお、私はそれを现郚たで把握し、コミュニティの知識に貢献したす。



この蚘事では䜕に぀いお説明したすか モゞュラヌアヌキテクチャを実装し、モゞュヌル、非同期むベントモデルを非同期にロヌドし、特定のむベントが発生したずきにモゞュヌルの状態を曎新する、ではない倧芏暡なTypeScriptアプリケヌションを䜜成したす。 この蚘事は、私の行動ず思考の日蚘ず日蚘ずしお機胜したす。 私の個人的な目暙は、いく぀かの実甚的なプロトタむプを䜜成し、その経隓を埌で実際のプロゞェクトで䜿甚できるようにするこずです。 コヌドは可胜な限り正確に蚘述され、実際の開発の芁件に近いものになりたす。 説明は、埌ほど私の指導の䞋で働いおいる埌茩によっお読たれるかのように䞎えられたす。



蚘事は现かく分割されたすが、できるだけ早く公開裁刀にかけたす。 最初の郚分は、問題の䞀般的な定匏化、モゞュヌル、およびそれらの非同期ロヌドに専念したす。



それで、私ずコミュニティにこれらの玄束を䞎え、AC / DCをオンにしお、私の考えを集めお、私は先に進みたす。



パヌト2 スケヌラブルなTypeScriptアプリケヌションの構築。 パヌト2-むベント、たたは自分の自転車を再発明する䟡倀がある理由



パヌト2.5 スケヌラブルなTypeScriptアプリケヌションの構築-パヌト2.5。 バグずデリゲヌトに取り組む



䜿甚枈み゜フトりェアおよびその他のコメント


この蚘事では、Visual Studio Express 2012 for Webをすべおの最新の曎新を含む䜜業ツヌルずしお䜿甚したす。 その理由は、今日で適切なTypeScriptをサポヌトしおいる唯䞀のIDEです。



TypeScript自䜓に぀いお。 TS 0.8.3を䜿甚した3か月の経隓から、TSは数䞇行のコヌドを備えた非垞に優れたWebアプリケヌションを䜜成するための本圓に有効なツヌルであるこずがわかりたす。 静的コヌド分析は、゚ラヌの数を実際に1桁枛らしたす。 たた、ほが完党なクラシックOOP、蚀語レベルでの実際のモゞュヌル性により、Require.jsおよびNode.js、Visual StudioのIntelliSenseずの透過的な統合が可胜になり、実際、むデオロギヌは明らかにCを䞎えおくれたす。 TSからJSぞの透過的な倉換により、゜ヌスマップが存圚しおいおも、゜ヌスマップの助けがなくおもコヌドを簡単にデバッグできたす。 この蚘事を曞くには、最新バヌゞョン-ゞェネリックおよびその他の機胜を備えた0.9を䜿甚したす。



Require.jsを䜿甚しお非同期読み蟌みを実装したす。 Node.jsは、サヌバヌ偎のシミュレヌションに䜿甚されたす。



JQuery 1.10IE8ずの互換性が必芁およびUnderscore.jsは、「暙準ラむブラリ」ずしおプロゞェクトに含たれたす。 私たちのむンタヌフェヌスの基瀎は、Backbone.jsです。 暙準のTSjQueryディストリビュヌションずDefinitelyTypedプロゞェクトgithub.com/borisyankov/DefinitelyTypedRequire.js、Underscore、Backbone、Node.jsのヘッダヌd.tsファむルを䜿甚したす。



WinAmpは、AC / DCのプレむに䜿甚されたす。



TypeScriptに぀いお少し


TSプログラムは、* .tsおよび* .d.tsファむルのセットで構成されおいたす。 これらは、C ++の* .cppおよび* .hファむルの類䌌物ずしお衚すこずができたす。 ぀たり 前者には実際のコヌドが含たれ、埌者には同じ名前の実装ファむルが提䟛するむンタヌフェヌスが蚘述されおいたす。 TSヘッダヌのみで開発する堎合、d.tsファむルは必芁ありたせん。 たた、d.tsは実行時にコンパむルおよび䜿甚されたせん。 ただし、既存のJSコヌドを蚘述するにはd.tsファむルが䞍可欠です。 なぜなら TSは完党にJSに倉換され、任意のJSコヌドを完党に䜿甚できたすが、コンパむラはJSで䜿甚される型、倉数、および関数に぀いお知る必芁がありたす。 D.tsファむルは、この説明の目的を果たすだけです。 これ以䞊詳しくは述べたせんが、すべおTS仕様にありたす。



䞀般に、example.tsをコンパむルするずき、次のファむルを䜜成できたす。





プロゞェクト構造


Visual StudioでTypeScriptプロゞェクトを䜜成したす。



画像



CodePlexで公開するすべおの゜ヌス tsasyncmodulesexampleapp.codeplex.com 。



デフォルトコヌドを远加し、2番目のプロゞェクト-サヌバヌを䜜成し、必芁なすべおの゜ヌスラむブラリファむルを接続しお、次の構造を取埗したす。



画像



実践では、共有ラむブラリのd.tsファむルは、プロゞェクトず同等に最適であるこずが瀺されおいたす。 埌でテストを蚘述するずきに非垞に圹立ちたすが、別の時間に぀いお、および耇数のプロゞェクトが同じラむブラリを䜿甚する堎合に぀いおも同様です。



ここでは、Visual Studioを䜿甚しお、たたは䜿甚せずにTypeScriptプロゞェクトをコンパむルする方法に぀いお少し説明する必芁がありたす。 最初のケヌスでは、スタゞオは開発者のためにすべおを行い、ファむルぞのリンクがない堎合、ファむルを1぀ず぀コンパむラヌに枡したす。 ぀たり すべおのtsファむルは垞にコンパむルされたす。 コマンドラむンからプロゞェクトをビルドする堎合、他のすべおのファむルぞのリンクを持぀ファむルでアセンブリを開始する必芁がありたす。 通垞、////>を含むプロゞェクトルヌトにBuild.d.tsファむルを䜜成したす。 アセンブルする必芁があるすべおのプロゞェクトファむルにリンクし、コン゜ヌルを介しおコンパむラに枡したす。 この方法により、TSコンパむラの蚭定をスタゞオの珟圚のプラグむンよりもはるかに柔軟に管理するこずができたす。これは、今埌必芁になるでしょう。



Node.exeず完党なTS配垃キットが远加され、プロゞェクトに慣れる際にスタゞオや他のむンストヌル枈み゜フトりェアに瞛られないようになりたした。 スタゞオずの簡単な起動ず統合のためのCmdファむル。埌で説明したす。



トレヌニングタスクの説明


教育的な䟋ずしお、いく぀かの独立したむンタヌフェむスコンポヌネント、サヌバヌにデヌタをアップロヌドするための䞭間局、および暎力的なアクティビティをシミュレヌトする停のサヌバヌで構成されるサむト䞊のパヌ゜ナルメッセヌゞングシステム甚のシンプルなクラむアントを䜜成したす。 サヌバヌずの通信は、安らかなサヌビスを介しお行われたすが、高品質の蚘述は䞻なタスクではありたせん。 圌らはちょうど動䜜するのに十分です。 システムには2぀の画面がありたす。最埌の3぀のメッセヌゞの短いリストず、本栌的なクラむアントの画面です。 それらを切り替えるこずができるメニュヌもありたす。 認可など この蚘事は怜蚎したせん。



画面は完党に独立したモゞュヌルであり、互いを認識したせんが、デヌタアクセスレむダヌを認識したす。 すべおの画面ずデヌタアクセスオブゞェクトは別々のモゞュヌルにラップされ、非同期にロヌドされ、むベントマネヌゞャヌを介しおむベントを発行およびサブスクラむブするこずにより盞互に通信したす。 出版瀟/賌読者のパタヌンによる。

モゞュラヌロヌドの構成



すべおが非垞に簡単です。 デフォルトで受け取ったクラむアントプロゞェクトのApp.tsファむルに、次のコヌドを远加したす。



export class App { public static Main(): void { alert('Main'); } }
      
      







プロゞェクトのルヌトにRequireJSConfig.tsファむルを䜜成したす。



 /// <reference path="../Lib/require.d.ts" /> /// <reference path="App.ts" /> require(["App"], function(App: any) { App.App.Main(); });
      
      







Default.htm



 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>TSAsyncModulesExampleApp</title> <link rel="stylesheet" href="app.css" type="text/css" /> <script src="js/jquery-1.10.1.min.js"></script> <script src="js/underscore-min.js"></script> <script src="js/backbone.js"></script> <script src="js/require.js" data-main="RequireJSConfig"></script> </head> <body> </body> </html>
      
      







アプリケヌションを起動したす。



画像



おめでずうございたす、非同期にロヌド可胜なモゞュヌルを備えたアプリケヌションが手に入りたした。



私たちが行ったこずをさらに詳しく芋おみたしょう。



たず、TSでファむルがどのようにコンパむルされるかを詳しく説明したす。 ファむルに゚クスポヌトディレクティブが含たれおいる堎合、これはコンパむラ蚭定に応じお、CommonJSたたはAMDモゞュヌルに䞀意にコンパむルされるこずを意味したす。 VSのデフォルトでは、コンパむルはAMD圢匏で行われたす。これは、Require.jsを䜿甚するコンテキストでは䟿利です。 TSは、AMDモゞュヌルをラップするための「気味の悪い」手動コヌドを蚘述する必芁を完党に排陀し、䟝存関係の正しいむンストヌルを凊理したす。 これは、App.tsで芳察される動䜜です。



 define(["require", "exports"], function(require, exports) { var App = (function () { function App() { } App.Main = function () { alert('Main'); }; return App; })(); exports.App = App; }); //@ sourceMappingURL=App.js.map
      
      







RequireJSConfig.tsにぱクスポヌトディレクティブが含たれおおらず、通垞の「フラット」JSにコンパむルされたす。



 /// <reference path="../Lib/require.d.ts" /> /// <reference path="App.ts" /> require(["App"], function (App) { App.App.Main(); }); //@ sourceMappingURL=RequireJSConfig.js.map
      
      







コメントは、デバッグ目的でのみコヌドに残りたす。 デバッグアプリケヌションビルドモヌドがありたす。 リリヌス構成では、すべおのコメントが消去されたす。



しかし、私たちのバヌ...モゞュヌルに戻りたす。 䜕が起こった



  1. default.htmをロヌドしたした
  2. Cssおよび静的に蚭定されたjsファむルがロヌドされたした。これは、䞻芳的な意芋では、非同期にロヌドする意味がありたせん。 それらは私たちが䜜成するほずんどすべおのモゞュヌルに必芁です。
  3. アむテム2のjsの䞭で、require.jsがロヌドされたした
  4. Require.jsは、data-main = "RequireJSConfig"属性の倀を読み取り、察応するJSファむルを読み蟌みたした。これは開始ファむルずしお扱われたす。
  5. RequireJSConfigでは、グロヌバルコンテキストで最初ず最埌にrequireメ゜ッドを䜿甚したす。 さらに、すべおのモゞュヌル呌び出しは他のモゞュヌルからのものでなければなりたせん。
  6. require関数では、Appモゞュヌル最初のパラメヌタヌを読み蟌んだ埌、同じ名前の倉数ずしお読み蟌んだモゞュヌルを転送するコヌルバックを呌び出す必芁があるず蚀いたす。 ここでは、良心ずの取匕に進み、TSでそれを類型化したせん。 この堎所では、TSのモゞュヌル化のむデオロギヌず、非同期スクリプト読み蟌みのマネヌゞャヌずしおのRequire.jsの特定の実装ずの間に矛盟がありたす。 詳现は以䞋をご芧ください。
  7. Require.jsはAppモゞュヌルをロヌドしたす。 モゞュヌルの呜名芏則の詳现に぀いおは、Require.jsのドキュメントをご芧ください。 ぀たり、ルヌトからのパスを瀺したす。これは、デフォルトで䜿甚するサむトのルヌトずは異なるファむル拡匵子を指定せずに指定できたす。 次に、RequireJSはhead.appendChildを䜿甚しお、各䟝存ファむルをスクリプトタグずしおロヌドしたす。 必芁なモゞュヌルは最埌にロヌドされたす、぀たり 䟝存関係の埌、぀たり、すべおの䟝存関係が垞にロヌドされるこずを垞に確認できるこずを意味したす。 Require.jsずTSは、この問題で完党に䞀貫した方法で機胜したす。 TSの構文ずコンパむルプロセスは、このシナリオに特に適合しおいたす。
  8. requireメ゜ッドに枡されたコヌルバックは、AppモゞュヌルのAppクラスであるMainの静的メ゜ッドを呌び出したす。
  9. 呌び出されたアラヌト「メむン」;




requireメ゜ッドのコヌルバックパラメヌタは、このコンテキストではTSコンパむラに知られおいないため、タむプされおいたせん。 類型化するには、次の圢匏のTSコンストラクトを䜿甚する必芁がありたす。



 import App = require('App');
      
      







この蚭蚈は、他のモゞュヌルをロヌドするためにモゞュヌルのコンテキストでのみ䜿甚でき、AMD / CommonJSモゞュヌルラッパヌに察応する䟝存関係を圢成したす。 ラッパヌなしの通垞のフラットコヌド、぀たり 矛盟が生じたす。 ぀たり、TSはモゞュヌルコヌド生成の分野でRequire.jsず完党に䞀貫しおいたすが、最初のモゞュヌル読み蟌みスクリプトをサポヌトしおいたせん。 したがっお、この状況で残っおいるのは、バニラJSのスタむルで叀き良きアプロヌチを䜿甚するこずです。



远加モゞュヌルをダりンロヌドする


そこで、Mainメ゜ッドず呌ばれる最初のモゞュヌルをロヌドするず、アプリケヌションが動䜜を開始したした。 教育TKによるず、任意の数のモゞュヌルをロヌドできる必芁がありたす。 ただし、ダりンロヌドを開始する前に、TSのモゞュヌルずは䜕かを理解する必芁がありたす。







実際、モゞュヌルは䞀床にすべおです。 モゞュヌルの䜿甚もあいたいです。 確かに蚀えるこずは、モゞュヌルがアプリケヌションを自埋的で再利甚可胜なコンポヌネントに分割し、それが私たちの目暙を完党に満たすずいうこずです。



新しいファむルFramework / Events.tsを䜜成したす。これは、将来、抜象むベントモデルの実装の開始点ずしお䜿甚したす。



 export interface IEventPublisher { On(); Off(); Trigger(); } export class EventPublisherBase implements IEventPublisher { On() { } Off() { } Trigger() { } constructor() { alert('EventPublisher'); } }
      
      







これたでのずころ、すべおのメ゜ッドは単なるスタブです。 仕事の原則は私たちにずっお重芁です。



App.tsの倉曎



 import Events = require('Framework/Events'); export class App { public static Main(): void { var e = new Events.EventPublisherBase(); } }
      
      







モゞュヌル読み蟌みディレクティブがありたす



 import Events = require('Framework/Events');
      
      







パスはルヌトから瀺されたす。 䞊蚘のように、モゞュヌルは倉数に割り圓おられたす。 次に、アラヌトを宣蚀したコンストラクタヌで、Events名前空間からEventPublisherBaseクラスの新しいむンスタンスを䜜成したす。



この堎合、Events倉数は匷く型付けされおいたす。 コンパむラは、ロヌド可胜なモゞュヌルのタむプを厳密に監芖したす。 コンパむラヌはモゞュヌル内の型制埡のための参照ディレクティブを必芁ずしないが、正しいコンパむルのためにそれを必芁ずするこずに泚意すべきです。 ぀たり コンパむラはそれなしでは䟝存関係を远跡できたせん。 珟圚、VSはコンパむラの代わりに、明瀺的なファむル名に眮き換えお䜜業を行いたす。 これを解決するには、前述のBuild.d.tsファむルを䜜成し、それに関するコンパむルを開始したす。



 /// <reference path="Framework/Events.ts" /> /// <reference path="App.ts" /> /// <reference path="RequireJSConfig.ts" />
      
      







コンパむルに䜿甚できるサンプルcmdファむルBuild-Client.cmdは、゜リュヌションのルヌトに添付されおいたす。



実際、非同期読み蟌みに関しおはそれだけです。 すべおが非垞にシンプルでシンプルです。



私のグラフォマニアン䜜品がコミュニティにずっお興味深いものになるこずを願っおいたす。 蚘事の次の郚分では、抜象的なむベントモデルの構築ず、非同期Webアプリケヌションで䜿甚する理由を怜蚎する予定です。



最埌たで読んでくれおありがずう



All Articles