web-dev-qa-db-ja.com

RequireJSモジュール/パッケージの相対パス

私はRequireJSにかなり慣れていないので、少し問題に遭遇しました。私はRequireJSを使用してバックボーン上に構築された小さなフレームワークを作成しましたが、さまざまなプロジェクトで再利用できるようにしたいと考えています。したがって、いくつかの検索で、allowsパッケージが必要であることを学びました。これは私が探していたもののようでした。アプリを起動するためのmain.jsファイルがあり、基本的に次のようになります。

require.config({
  packages: ['framework']
});

require(['framework'], function(framework) {
  framework.createDash();
});

次に、私のmain.jsと同じディレクトリに、次のような別のmain.jsを含む「framework」という別のディレクトリがあります。

define(function(require, exports, module) {
  exports.createDash = function(dash, element) {
    require(['dash/dash.model', 'dash/dash.view'], function(DashModel, DashView) {
      return new DashView({
        model: new DashModel(dash),
        el: element ? element : window
      });
    });
  };
});

検索で this page が見つかりました。これは、 'require'引数をサブモジュールにスコープする必要があることを示しています。しかし、私が物事を要求しようとするとき、それらはまだ私のオリジナルのmain.jsに関連しています。私は多くのことを試し、何時間も検索して無駄になりました。ルート内のmain.jsに関連してパッケージ内にrequire/define呼び出しを含める方法はありますか?

28

Require構成でパッケージとしてサブモジュールを定義する必要があります:

require.config({
  packages: [
    { name: 'packagename',
      location: 'path/to/your/package/root',  // default 'packagename'
      main: 'scriptfileToLoad'                // default 'main' 
    }]
  ... some other stuff ...
});

モジュールをロードするには、必要なときに 'packagename'を使用するだけです。

define(['jquery', 'packagename'], function($, MyPackage) {
  MyPackage.useIt()
});

パッケージでは、サブモジュールに関連するファイルをロードするために./プレフィックスを使用する必要があります。

define(['globalDependency', './myLocalFile'], function(Asdf, LocalFile) {
  LocalFile.finallyLoaded();
});

便利なショートカットがあります。パッケージ名が場所と同じで、メインファイルの名前が「main.js」の場合、これを置き換えることができます。

  packages: [
    { name: 'packagename',
      location: 'packagename',
      main: 'main'
    }]

これに:

  packages: ['packagename']

私が見る限り、すでにパッケージを定義しようとしましたが、。/プレフィックスも使用しましたか?このプレフィックスがないと、requireはそのグローバルルートパスでファイルを検索しようとします。また、パッケージがないと、相対パスがグローバルルートパスと同じであるため、./は役に立たなくなります。


乾杯

51
Simon Goller

私は私の質問への答えと解決策を見つけました(明らかに同じではありませんでした)。将来誰かの役に立つかもしれないので、ここに投稿します。

基本的に私が望んでいたのは、独自のコンテキスト内でフレームワークをロードすることでした。 requireのWebサイトの 設定セクション使用方法の例 の下にコンテキストオプションを見つけました。もともと私は次のようなことをしてこれを試しました:

var req = require.config({
    baseUrl: 'framework',
    context: 'framework',

    paths: {
        jQuery: 'lib/jquery/jquery-1.7.min.js',
        Underscore: 'lib/underscore/underscore.min.js',
        Backbone: 'lib/backbone/backbone.min.js',
        etc...
    }
});

req(['main'], function() {});

これには2つの問題がありました。最初に、私の 'req'変数はフレームワークの外で定義されていましたが、フレームワークでそれ自体のパスを定義する必要がありました。そして次に、フレームワークの外のファイルがフレームワーク内のファイルを必要とするときはいつでも、たとえば「jQuery」が必要になると、フレームワークインスタンスのコンテキスト内からjQuery(または他の何でも)は必要ありません。必要ので、ファイルを見つけることができませんでした。

私がやったことは、フレームワークのmain.jsを次のように定義することでした。

var paths = {
    jQuery: 'lib/jquery/jquery-1.7.min.js',
    Underscore: 'lib/underscore/underscore.min.js',
    Backbone: 'lib/backbone/backbone.min.js',
    etc...
};

define(function() {
    var exports = {};

    exports.initialize = function(baseUrl, overridePaths, callback) {
        if(!overridePaths) {
        overridePaths = {};
        }
        if(baseUrl && baseUrl[baseUrl.length - 1] != '/') {
            baseUrl = baseUrl + '/';
        }

        var fullpaths = {};
        for(var path in paths) {
            // Don't add baseUrl to anything that looks like a full URL like 'http://...' or anything that begins with a forward slash
            if(paths[path].match(/^(?:.*:\/\/|\/)/)) {
                fullpaths[path] = paths[path];
            }
            else {
                fullpaths[path] = baseUrl + paths[path];
            }
        }

        var config = {paths: fullpaths};
        for(var pathName in overridePaths) {
            config.paths[pathName] = overridePaths[pathName];
        }
        require.config(config);

        // Do anything else you need to do such as defining more functions for exports

        if(callback) {
            callback();
        }
    }

    return exports;
});

そして、私のプロジェクトのmain.jsファイルで、次のようにします。

require(['framework/main'], function(framework) {
    // NOTE: This setTimeout() call is used because, for whatever reason, if you make
    //       a 'require' call in here or in the framework without it, it will just hang
    //       and never actually go fetch the files in the browser. There's probably a
    //       better way to handle this, but I don't know what it is.
    setTimeout(function() {
        framework.initialize('framework', null, function() {
            // Do stuff here
        }
    }, 0);
});

これは、 'baseURL'のフレームワークのinitialize()メソッドに渡されたものをすべて取り、フレームワークが定義する、スラッシュまたは 'anything://'で始まらないパスを上書きします。これにより、フレームワークを使用するパッケージが「jQuery」などをオーバーライドできるようになります。

5

これは私にとってはうまくいき、"./"接頭辞をモジュール名に:

define(function (require, exports, module) {
    exports.createDash = function (dash, element) {
        require([ './dash/dash.model', './dash/dash.view' ], function (DashModel, DashView) {
            return new DashView({
                model : new DashModel(dash),
                el : element ? element : window
            });
        });
    };
});
2
Paul Grime

Main.js(または他のパッケージmain)が特定の名前で呼び出されると仮定して、サブモジュールを含むパッケージをdata-mainまたは外部フレームワークから直接使用できるようにするために私にとってうまくいったプロセスは、[ var baseUrl = require.toUrl('packageName') + '/../'require.config({ paths: { ... } })構成ファイルの接頭辞として使用します。例えば:

var music21Base = require.toUrl('music21') + '/../';

require.config({ paths: {
                          'jquery': music21Base + 'ext/jquery/jquery.2.1.10.min';
                          'subModuleLoader': music21Base + 'src/subModuleLoader';
                         }  });

context: "xxx"の設定は、./modNameを使用して通常のモジュールを呼び出す場合は正常に機能しましたが、paths引数では機能しませんでした。