Node.jsにおけるRequireJS
Node.jsには既にモジュールローダーがありませんか? § 1
はい、Node.jsにはあります。そのローダーはCommonJSモジュール形式を使用します。CommonJSモジュール形式はブラウザには最適ではありません。また、CommonJSモジュール形式で行われたいくつかのトレードオフには同意できません。サーバーでRequireJSを使用することで、サーバー側でもブラウザ側でも、すべてのモジュールに1つの形式を使用できます。これにより、ブラウザでのRequireJSによる速度の向上とデバッグの容易さを維持し、2つの形式間の変換コストを心配する必要がなくなります。
モジュールに`define()`を使用したいが、サーバーでRequireJSを実行せずにNode.jsで実行したい場合は、以下のセクションでamdefineの使用について説明しています。
CommonJSモジュール形式で既に記述されているNode.jsモジュールを使用できますか? § 2
はい!RequireJSのNode.jsアダプターであるr.jsは、RequireJSで使用される設定でモジュールが見つからない場合、Node.jsの`require`の実装とNode.jsの検索パスを使用するため、既存のNode.jsベースのモジュールを変更することなく引き続き使用できます。
RequireJSは最初に設定オプションを使用してモジュールを検索します。RequireJSがその設定でモジュールを見つけられない場合、Node.jsの種類のモジュールと設定を使用するモジュールであると見なされます。そのため、RequireJS APIを使用するモジュールの場合のみ、RequireJSでモジュール位置を設定してください。Node.jsのAPIと設定/パスを期待するモジュールについては、npmなどのNode.jsパッケージマネージャーを使用してインストールし、RequireJSでその場所を設定しないでください。
ベストプラクティス:Node.js専用のパッケージ/モジュールをプロジェクトの**node_modules**ディレクトリにnpmを使用してインストールしますが、RequireJSがnode_modulesディレクトリ内を参照するように設定しないでください。また、Node.js専用のモジュールを参照するために相対的なモジュールIDを使用しないでください。そのため、**require("./node_modules/foo/foo")**のようなことは**しないでください**。
その他の注記
- Node.jsでのRequireJSは、ローカルディスク上にあるモジュールのみをロードできます。たとえば、http経由でモジュールを取得することは、現時点ではサポートされていません。
- `map`、`packages`、`paths`などのRequireJSの設定オプションは、RequireJSがモジュールをロードする場合にのみ適用されます。RequireJSがNode.jsのモジュールシステムに問い合わせる必要がある場合、元のIDがNode.jsに渡されます。Node.jsモジュールを`map`設定で使用するには、このメールリストのスレッドに示されているように、インライン`define()`呼び出しを使用します。
どのように使用しますか? § 3
Node.jsアダプターを取得するには2つの方法があります。
npm
npmを使用してインストールします。
npm install requirejs
このオプションでは、最新のリリースがインストールされます。
r.jsのダウンロード
npmを使用しない場合は、r.jsを直接取得できます。
- ダウンロードページからr.jsをダウンロードして、プロジェクトに配置します。
- r.jsリポジトリからソースを取得し、「node dist.js」でr.jsを生成するか、**dist**ディレクトリからスナップショットを取得します。
使用方法
これらの手順は、「requirejs」のnpmインストールを想定しています。r.jsファイルを直接使用している場合は、`require('requirejs')`を`require('./path/to/r.js')`に置き換えます。基本的な使い方は次のとおりです。
- `require('requirejs')`
- メインのjsファイルの"require"関数をrequirejsの設定に渡します。
例
var requirejs = require('requirejs');
requirejs.config({
//Pass the top-level main.js/index.js require
//function to requirejs so that node modules
//are loaded relative to the top-level JS file.
nodeRequire: require
});
requirejs(['foo', 'bar'],
function (foo, bar) {
//foo and bar are loaded according to requirejs
//config, but if not found, then node's require
//is used to load the module.
});
npmを介してインストールされたNode.js専用モジュールをロードできるようにRequireJSを設定する方法については、セクション2の注記をよくお読みください。
RequireJSを介してモジュールをロードしますが、他のものにはNode.jsネイティブモジュールを使用する、より完全な例については、r.jsリポジトリの埋め込みテストを参照してください。
**注記:**RequireJS 2.1以降では、`requirejs([], function() {})`は非同期的に関数コールバックを呼び出します(以前のバージョンでは同期的に呼び出されていました)。ただし、Node.jsで実行する場合、モジュールの読み込みは同期IO呼び出しを使用して行われ、ローダープラグインはロードメソッドへの呼び出しを同期的に解決する必要があります。これにより、`requirejs('stringValue')`呼び出しを介してNode.jsでのrequirejsモジュールの同期使用が機能します。
//Retrieves the module value for 'a' synchronously
var a = requirejs('a')
AMDまたはRequireJSを使用したNode.jsモジュールの構築
Node.jsでライブラリを使用するユーザーにRequireJSを使用させることなく、RequireJSとNode.jsの両方で機能するようにモジュールをコーディングしたい場合は、これを行うためにamdefineパッケージを使用できます。
if (typeof define !== 'function') {
var define = require('amdefine')(module);
}
define(function(require) {
var dep = require('dependency');
//The value returned from the function is
//used as the module export visible to Node.
return function () {};
});
バージョン1.0.3以降のRequireJSオプティマイザーは、上記の「amdefine」の使用を削除するため、このモジュールをWebベースのプロジェクトにも安全に使用できます。上記の**正確な「amdefine」if()テストと内容を使用してください**。スペース/改行の違いは許可されます。詳細については、amdefineプロジェクトを参照してください。
RequireJSを直接使用してモジュールをコーディングし、そのアプリがRequireJSを使用することを要求せずに、他のNode.jsプログラムで使用できるようにNode.jsにモジュール値をエクスポートする場合は、次の例にリストされているアプローチを使用できます。
`baseUrl`をモジュールを含むディレクトリに具体的に設定するのが最善です。これにより、`node_modules`階層内にネストされている場合でも適切に機能します。同期的な`requirejs('moduleId')`を使用して、requirejsの設定とルールを使用してモジュールを取得し、Node.jsの`module.exports`を使用してモジュール値をエクスポートします。
var requirejs = require('requirejs');
requirejs.config({
//Use node's special variable __dirname to
//get the directory containing this file.
//Useful if building a library that will
//be used in node but does not require the
//use of node outside
baseUrl: __dirname,
//Pass the top-level main.js/index.js require
//function to requirejs so that node modules
//are loaded relative to the top-level JS file.
nodeRequire: require
});
//foo and bar are loaded according to requirejs
//config, and if found, assumed to be an AMD module.
//If they are not found via the requirejs config,
//then node's require is used to load the module,
//and if found, the module is assumed to be a
//node-formatted module. Note: this synchronous
//style of loading a module only works in Node.
var foo = requirejs('foo');
var bar = requirejs('bar');
//Now export a value visible to Node.
module.exports = function () {};
オプティマイザーをNode.jsモジュールとして使用
Node.jsモジュールは、コマンドラインツールではなく関数呼び出しを介してRequireJSオプティマイザーを使用するための**optimize**メソッドとしてもRequireJSオプティマイザーを公開しています。
var requirejs = require('requirejs');
var config = {
baseUrl: '../appDir/scripts',
name: 'main',
out: '../build/main-built.js'
};
requirejs.optimize(config, function (buildResponse) {
//buildResponse is just a text output of the modules
//included. Load the built file for the contents.
//Use config.out to get the optimized file contents.
var contents = fs.readFileSync(config.out, 'utf8');
}, function(err) {
//optimization err callback
});
これにより、Webビルダーなど、他の最適化ワークフローを構築できます。これは、「</body>タグの前に1つのスクリプトファイルを含める」アプローチで常に開発することを好む場合に使用できます。Node.jsで実行されるオプティマイザーは非常に高速ですが、ビルドの一部であるスクリプトを変更した場合にのみビルドを再生成したくない大規模なプロジェクトの場合、Node.jsの`fs.watchFile()`を使用してファイルを監視し、ファイルの変更時にビルドをトリガーできます。
フィードバック
問題が発生し、報告したい場合は、r.js GitHub Issuesページを使用してください。