まず第一に、これは一意の解決策を持つ質問ではありません。私のために機能する 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 ファイルからページ固有のモジュールを要求しないことが私の解決策です。代わりに、メイン ファイルからすべての共有コード (サード パーティと私自身) を要求し、ページ固有のコードを各ページにロードします。メイン ファイルは、すべての共有/lib ファイルをロードした後、ページ固有のコードを開始するローダーのみになります。
これは、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 つのリクエストを行います。r.js にパッケージを作成してこれら 3 つのファイルを含めるように指示することで、これを回避できます。
ビルド プロファイルの "modules" 属性:
...
"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。node と node 用の r.js モジュールをインストールし、build.cmd を実行するだけです (/build ディレクトリ内。そうしないと、相対パスを使用するため失敗します)。
私がはっきりしていることを願っています。何か変な感じがしたら教えてください ;)
よろしく!