16

Grails (REST-API、AngularJS の一部、MongoDB、Tomcat、Spock、いくつかのプラグイン) から Node.js + Angular.js への移行に関する (ソフトウェア) アーキテクチャに関する質問がいくつかあります。おそらく、Grails プロジェクトの最初の構造について説明する必要があるので、ここで説明します。

いくつかのプラグインで構築されたメインの Grails アプリケーション (いくつかの他のアプリケーションに加えて) があります。これらのプラグインはそれぞれ単独で実行できます。つまり、独自の UI、個別のテンプレート、サービス、コントローラー、ルート、テストなどがあります。また、さまざまなリポジトリでホストされています。これは、Grails プラグインのメカニズムによって行われます。利点は、テストの労力が少なくて済むこと、コンパイル時間の短縮、モジュール化、単一の責任などです。

それでも、コンパイルとテストにかかる時間は非常に高くつきます。また、API がテンプレート/ビューの一部を提供するという事実も好きではありません。バックエンド API を「バックエンド API にするだけ」、フロントエンドを「フロントエンドにするだけ」にしたいと考えています。したがって、各 AngularJS アプリケーション/プラグインは独自のビュー、ルート、サービスなどを提供します。ただし、他のプラグインに依存する場合もあります。

だから私が達成したいのは次のとおりです:

  • いくつかのプラグインを含む 1 つの主要な AngularJS アプリケーション (プラグインは、レポート ジェネレーター、ゲストブックなどのようなものであり、アプリケーションの単一の独立した部分について言えば、特定のルートまたはページのごく一部を使用します) )。
  • 各プラグインは、スタンドアロンの AngularJS アプリケーションでなければなりません (おそらく、開発中に grunt などを介して実行可能です)。UI 開発者がバックエンド アプリケーション全体を起動する必要がないように、さらに JavaScript のみで機能テストを実行できるようにします。
  • REST を介した通信のみ。フロントエンドは API からすべてのデータを取得する必要があります
  • 各プラグインは単独でテスト可能でなければなりません
  • プラグインが動作するために他のプラグインが必要になる場合があります
  • メインの index.html (および app.js?) は、バックエンド (API) の残りの部分から切り離された Nginx サーバーによって提供される場合があります。

頭の中に具体的なイメージがありますが、このアーキテクチャをセットアップする方法に苦労しています。

Grails では、プラグイン メカニズムは、プラグインに依存する設定 (URL マッピング、依存関係など) を、それらが含まれる/注入されるメイン アプリケーションにマージします。これは、AngularJS でも達成したいことです。そう:

  • AngularJS にも同じようなメカニズムはありますか?
  • 各プラグインのルートをメイン アプリケーションに提供/マージするにはどうすればよいですか?
  • アプリケーションとプラグインの依存関係を宣言するにはどうすればよいですか?
  • ビルド プロセスに役立つツールは何ですか?
  • プラグイン リソース (css/less ファイル、ビュー、サービスなど) の遅延取得を確立する方法は?
  • アプリケーションが起動時にプラグインのすべてのリソースを提供するのを防ぎます (起動時にルートが必要だと思います)

これは単なるやり方の質問ではないので、重要な部分が欠けていたり、いくつかの部分が十分に明確でない場合は、申し訳ありません。質問していただければ、それぞれの質問に詳しくお答えします。

4

2 に答える 2

4

** この回答は不完全です **

これを掘り下げる前に、あなたを理解していることを確認したい.

これは、遅延読み込み (プラグイン、ベンダー アセット、管理者など) を管理するローダー モジュールの簡単な実装です。

これは役に立ちますか?

angular.module('Bizcoin.loader')
.service('Loader', Loader);

function Loader($injector, $ocLazyLoad, User) {
  var Loader = {
    load: load,
    get: get,
    plugins: {},
    flags: {}
  };

  init();

  return Loader;

  function init() {
    load('vendors');
    if (userIsAdmin)
      load('admin');
  }

  function load(plugin) {
    Loader.plugins[plugin] = Loader[plugin] || $ocLazyLoad.load('path/to/'+plugin+'.js');
    return Loader.plugins[plugin].then(setFlag);

    function setFlag() {
      return Loader.flags[plugin] = true;
    }
  }

  function get(plugin) {
    return load(plugin).then(function() {
      return $injector.get(plugin);
    });
  }

}
于 2015-08-11T23:46:54.547 に答える
3

私は、20 以上の独立したエリア (またはモジュール) と、すべてのエリアで共通して再利用されるいくつかのコア機能で構成される大規模な .Net/AngularJS アプリケーションに取り組んでいます。

私の特定のケースでこれを行う方法について詳しく説明しましょう。いくつかのアイデアが得られるかもしれません。私が .Net を使用しているという事実は、ここでは関係ありません。これは、どのフレームワークでも実現できるからです。

各エリアは、常に存在するコア機能のみに依存する独立したアプリケーションとして機能します。各エリアには独自の ASP.Net MVC ルートがあります。各エリアは、提供したいメニュー リンクをコア アプリケーションに登録します。顧客がアプリケーション ダッシュボードにアクセスすると、アプリケーションのコア部分のみが表示されます。ユーザーがメニューのリンクをクリックすると、エリアの 1 つによって提供されるコンテンツに移動し、そのエリアのコアとアセットのみが読み込まれます。

これがどのように行われるか見てみましょう。

アプリケーションのメイン ページで、次のようなスクリプトをロードします。

<script type="text/javascript">
    // a JS object with all the necessary app data from the server.
    // e.g.: menu data, etc
    window.appContext = @Html.Action("ApplicationContext", "Portal")); 
</script>

@Scripts.Render("~/bundles/angular-main")

@RenderSection("AngularAreas", required: false)

私はドット .Net バンドルとセクションを利用しています。

アプリケーションのメイン (コア) AngularJS 部分は、Angular 構成、国際化サービス、グローバル通知サービス、再利用可能な UI コンポーネントなどで構成されてい@Scripts.Render("~/bundles/angular-main")ます。

ユーザーがその@RenderSection("AngularAreas", required: false)エリアに移動すると、セクションは各エリアによって埋められます。

AngularJS コードを見てみましょう。これはメインの app.ts の一部です。

// If user is visiting an Area, the NgModules array will be augmented.
// with the modules the Area wants to provide (to be bootstrapped)
export var LoadNgModules = [
    NgModules.Config,
    NgModules.Core
];

angular.module(NgModules.Bootstraper, LoadNgModules);

angular.element(document).ready(function () {
    angular.bootstrap(document, [NgModules.Bootstraper]);
});

エリアの例を見てみましょう。

次に、Area がそのアセットを提供し、 で出力する方法を示します@RenderSection("AngularAreas", required: false)

@section AngularAreas {
    @Scripts.Render("~/bundles/areas/staff-management")
}

そのエリアのすべてのスクリプトを含む単純なバンドルです。では、このエリアの AngularJS コードの重要な部分を見てみましょう。

var StaffManagementNgModule = 'areas.staff-management';

// Push our self into the modules to be bootstrapped
LoadNgModules.push(StaffManagementNgModule );

// Define the module
angular
    .module(StaffManagementNgModule , ['ngRoute', NgModules.Core])
    .config([
        '$routeProvider', '$locationProvider', ($routeProvider: ng.route.IRouteProvider, $locationProvider) => {

            $routeProvider
                .when(staff', { template: '<staff></staff>' })
                .when('staff/details/:id', { template: '<staff-details></staff-details>' });
        }
    ]);;

以上で、Area は通常の Angular アプリケーションになります。

要約すると、主要な (コア) AngularJS 機能をロードし、領域が独自のモジュールで満たすことができる LoadNgModules 配列を提供します。

Area スクリプトと「自分自身」を LoadNgModules 配列にロードします。

最後に angular.bootstrap を実行します。

完全を期すために、領域が使用可能であることをメイン アプリケーションに示す方法を示す C# のフラグメントを次に示します。

public class ItemManagementModuleRegistration : IModuleRegistration
{
    public void Register(ModuleContext moduleContext)
    {
        string thisAreaName = "Staff";

        moduleContext.RegisterMenu(menuContext =>
        {
            var ItemsMenu = menuContext.Items(thisAreaName);

            // add urls and stuff...
        });

        // register more stuff with the moduleContext
    }
}

リフレクションを使用すると、どの領域が「インストール」されているかを簡単に見つけることができます。

これらは、セットアップの主な可動部分です。各エリアは独自の API とテストを持つことができます。それは非常に柔軟です。

于 2016-05-27T19:18:48.903 に答える