web-dev-qa-db-ja.com

複数ページのプロジェクトでRequireJSビルドプロファイル+ r.jsを使用する方法

私は現在、RequireJSの基礎を学んでおり、ビルドプロファイル、メインファイル、および複数ページのプロジェクトでのRequireJSの使用に関していくつか質問があります。

私のプロジェクトのディレクトリ構造は次のとおりです。

 httpdocs_siteroot /
 app /
 php files ... 
 media /
 css /
 css files ... 
 js /
 libs /
 jquery.js 
 require.js 
 mustache.js 
 mains /
 main。 page1.js 
 main.page2.js 
 main.page3.js 
 plugins/
jquery.plugin1.js
jquery.plugin2.js 
 jquery.plugin3.js 
 utils /
 util1.js 
 util2.js 
 images /

このプロジェクトはシングルページアプリではないため、ページごとに個別のメインファイルがあります(ただし、一部のページでは同じメインファイルを使用しています)。

私の質問は次のとおりです。

  1. RequireJSは、単一ページではないプロジェクトでも実用的ですか?

  2. オプティマイザーを使用しない場合、私のメインファイルはそれぞれ基本的に同じ構成オプションで始まります。

    requirejs.config({
      paths: {
        'jquery': 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min'
      },
      baseUrl: '/media/js/',
      // etc...
    });
    require(['deps'], function() { /* main code */ });
    

    これを回避する方法はありますか?実際にビルドしなくても、各メインファイルに同じビルドプロファイルを含めるのと同じですか?

  3. R.jsはhttpdocs_siterootの親ディレクトリ?

  4. アプリのディレクトリ構造またはRequireJSの使用に明らかに問題がありますか?

33
AndyPerlitch

まず第一に、これはユニークなソリューションの問題ではありません。私のために動作するRequireJSの使用方法を説明します。

第二に、英語は私の母国語ではありません。言語に関する訂正とヒントは非常に高く評価されます。お気軽に、みんな:)

1)require jsは、単一ページではないプロジェクトでも実用的ですか?

場合によります。たとえば、プロジェクトがページ間でコードを共有していない場合、RequireJSヘルプは控えめになります。 RequireJSの主なアイデアは、アプリケーションを再利用可能なコードのチャンクにモジュール化することです。アプリケーションがページ固有のコードのみを使用する場合、RequireJSを使用することはお勧めできません。

2)オプティマイザーを使用しない場合、各メインファイルは基本的に同じ構成オプションで始まります。これを回避する方法はありますか?実際にビルドしなくても、各メインファイルに同じビルドプロファイルを含めるのと同じですか?

私が見る唯一の方法は、メインファイルで構成を行うか、RequireJSを構成するモジュールを作成し、そのモジュールをmain.jsへの最初の依存関係として使用することです。しかし、これには注意が必要です。私は自分のアプリケーションで多くのmain.jsファイルを使用していません。私はローダーとして機能するものだけを使用します(以下を参照)。

3)r.jsはhttpdocs_siterootの親ディレクトリに配置する必要がありますか?

必ずしも。すべてのクライアントのものがそこにあるので、/ mediaディレクトリの中に置くことができます。

4)アプリのディレクトリ構造またはrequirejsの使用に明らかに問題がありますか?

私はそれを言わないでしょう。一方、構造はおそらく少し断片化しすぎています。たとえば、すべての「サードパーティ」を/ vendorディレクトリに置くことができます。しかし、これは単なる砂糖です。あなたの構造はうまく機能し、正しいようです。主な問題は、複数のメインファイルでのrequirejs.config()呼び出しだと思います。

私はあなたが今抱えているのと同じ問題を抱えていました、そして私は次の解決策に行き着きました:

1)非AMD準拠ファイルを定義でラップしないでください。動作しますが、requirejs.configの「shim」プロパティを使用して同じ結果を得ることができます(以下を参照)。

2)マルチページアプリケーションでの解決策は、最適化されたmain.jsファイルからページ固有のモジュールを要求しないことです。代わりに、メインファイルからすべての共有コード(サードパーティと自分のもの)を必要とし、ページ固有のコードを各ページにロードします。メインファイルは、すべての共有/ライブラリファイルをロードした後にページ固有のコードを開始するローダーになってしまいます。

これは、requirejsを使用してマルチページアプリケーションを構築するために使用するボイラープレートです

ディレクトリ構造:

/ src-すべてのクライアントのものをsrcディレクトリ内に配置したので、このディレクトリ内でオプティマイザを実行できます(これはメディアディレクトリです)。

/ src/vendor-require.jsを含むすべてのサードパーティのファイルとプラグインをここに配置します。

/ src/lib-ここに、アプリケーション全体または一部のページで共有されるすべての独自のコードを配置します。つまり、ページ固有ではないモジュールです。

/ src/page-module-xx-次に、ページごとに1つのディレクトリを作成します。これは厳密な規則ではありません。

/ src/main.js:これは、アプリケーション全体の唯一のメインファイルです。そうなる:

  • シムを含むRequireJSを構成します
  • 共有ライブラリ/モジュールをロードする
  • ページ固有のメインモジュールをロードする

これはrequirejs.config呼び出しの例です。

_requirejs.config({
        baseUrl: ".",
        paths: {
            // libraries path
            "json": "vendor/json2",
            "jquery": "vendor/jquery",
            "somejqueryplugion": "vendor/jquery.somejqueryplufin",
            "hogan": "vendor/hogan",

            // require plugins
            "templ": "vendor/require.hogan",
            "text": "vendor/require.text"
        },
        // The shim section allows you to specify 
        // dependencies between non AMD compliant files.
        // For example, "somejqueryplugin" must be loaded after "jquery".
        // The 'exports' attribute tells RequireJS what global variable
        // it must assign as the module value for each shim.
        // For example: By using the configutation below for jquery, 
        // when you request the "jquery" module, RequireJS will 
        // give the value of global "$" (this value will be cached, so it is
        // ok to modify/delete the global '$' after all plugins are loaded.
        shim: {
            "jquery": { exports: "$" },
            "util": { exports: "_" },
            "json": { exports: "JSON" },
            "somejqueryplugin": { exports: "$", deps: ["jquery"] }
        }
    });
_

次に、構成後、これらすべてのライブラリに対して最初のrequire()要求を行い、その後、「ページメイン」モジュールに対して要求を行うことができます。

_//libs
require([
    "templ",     //require plugins
    "text",
    "json",      //3rd libraries
    "jquery",
    "hogan", 
    "lib/util"  // app lib modules
 ],
    function () {
        var $ = require("jquery"),
            // the start module is defined on the same script tag of data-main.
            // example: <script data-main="main.js" data-start="pagemodule/main" src="vendor/require.js"/>
            startModuleName = $("script[data-main][data-start]").attr("data-start");

        if (startModuleName) {
            require([startModuleName], function (startModule) {
                $(function(){
                    var fn = $.isFunction(startModule) ? startModule : startModule.init;
                    if (fn) { fn(); }
                });
            });
        }
    });
_

上記のrequire()の本文でわかるように、require.jsスクリプトタグに別の属性が必要です。 data-start属性は、現在のページのモジュールの名前を保持します。

したがって、HTMLページに次の追加属性を追加する必要があります。

_<script data-main="main" data-start="pagemodule/main" src="vendor/require.js"></script>
_

これを行うことにより、「/ vendor」および「/ lib」ディレクトリ(共有リソース)内のすべてのファイルを含む最適化されたmain.jsが作成されますが、ページ固有のスクリプト/モジュールは含まれません。 main.jsに依存関係としてハードコーディングされています。ページ固有のモジュールは、アプリケーションの各ページに個別にロードされます。

「ページメイン」モジュールは、上記の「アプリメイン」によって実行されるfunction()を返す必要があります。

_define(function(require, exports, module) {
    var util = require("lib/util");

    return function() {
        console.log("initializing page xyz module");
    };
});
_

[〜#〜]編集[〜#〜]

これは、ビルドプロファイルを使用して、複数のファイルを持つページ固有のモジュールを最適化する方法の例です。

たとえば、次のページモジュールがあるとします。

/page1/main.js

/page1/dep1.js

/page1/dep2.js

このモジュールを最適化しない場合、ブラウザはスクリプトごとに1つずつ、合計3つのリクエストを行います。これを回避するには、パッケージを作成してこれら3つのファイルを含めるようにr.jsに指示します。

ビルドプロファイルの「モジュール」属性:

_...
"modules": [
   { 
      name: "main"  // this is our main file
   },
   {
        // create a module for page1/main and include in it
        // all its dependencies (dep1, dep2...)
        name: "page1/main",
        // excluding any dependency that is already included on main module
        // i.e. all our shared stuff, like jquery and plugins should not
        // be included in this module again.
        exclude: ["main"]
   }
]
_

これを行うことにより、すべての依存関係を持つ別のページごとのメインファイルを作成します。ただし、すべての共有コンテンツをロードするメインファイルがすでにあるので、それらをpage1/mainモジュールに再度含める必要はありません。複数のスクリプトファイルがあるページモジュールごとにこれを行う必要があるため、構成は少し冗長です。

ボイラープレートのコードをGitHubにアップロードしました: https://github.com/mdezem/MultiPageAppBoilerplate 。これは動作する定型文です。ノードとノードのr.jsモジュールをインストールし、build.cmdを実行します(/ buildディレクトリ内、それ以外の場合は相対パスを使用するため失敗します)

はっきりしているといいのですが。何か奇妙に聞こえたら教えてください;)

よろしく!

57
Marcelo De Zen
<script data-main="js/main" src="js/lib/require.js"></script>


// file: js/main

require(['./global.config'], function(){
    require(['./view/home'], function() {
        // do something
    });
});

これは私が私のプロジェクトで使用したものです。

1
John Xiao