Relative paths with RequireJS modules/packages

后端 未结 4 1168
悲哀的现实
悲哀的现实 2021-01-30 02:58

I\'m fairly new to RequireJS and I\'ve run into a bit of a problem. I\'ve written a little framework built on Backbone using RequireJS and I want it to be re-usable in different

相关标签:
4条回答
  • 2021-01-30 03:05

    I figured out the answer to my question, and the solution (they were not the same apparently). I guess I'll post it here in case it can help someone else in the future.

    Essentially what I was wanting was to load my framework within its own context. I found the context option under the configuration section on require's website and an example of how to use it. Originally I tried this by doing something like:

    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() {});
    

    There were two problems with this. First, my 'req' variable was being defined outside of the framework, but I wanted the framework to define it's own paths. And second, whenever a file outside of the framework would require a file within the framework, which would in turn require 'jQuery', for example, then jQuery (or whatever else) wouldn't be required from within the context of the framework instance of require and so it couldn't find the file.

    What I ended up doing was defining my framework's main.js to look something like this:

    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;
    });
    

    And then in my project's main.js file I just do this:

    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);
    });
    

    This takes whatever is passed in to the framework's initialize() method for 'baseURL' and prepends that to any paths that the framework defines that do not start with a forward slash or 'anything://', unless they are override paths. This allows the package using the framework to override things like 'jQuery'.

    0 讨论(0)
  • 2021-01-30 03:12

    This worked for me, adding a "./" prefix to the module names:

    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
                });
            });
        };
    });
    
    0 讨论(0)
  • 2021-01-30 03:22

    A process that worked well for me for allowing a package with submodules to be used directly from data-main or from an outside framework, assuming that a main.js (or other package main) is called by a particular name, was to use var baseUrl = require.toUrl('packageName') + '/../' as a prefix to a require.config({ paths: { ... } }) configuration file. For instance:

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

    The setting of context: "xxx" worked fine for calling normal modules with ./modName but did not work for the paths argument for me.

    0 讨论(0)
  • 2021-01-30 03:23

    You need to define your submodule as package in the require configuration:

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

    To load your module you just need to use your 'packagename' at the requirements:

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

    In your package you must use the ./ prefix to load your files relative to your submodule:

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

    There is a useful shortcut: If your package name equals to your location and your main file is called 'main.js', then you can replace this

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

    to this:

      packages: ['packagename']
    

    As far as I can see, you already tried to define a package but did you also use the ./ prefix? Without this prefix require will try to find the files in it's global root-path. And without a package, ./ will be useless because the relative path is the same as the global root-path.


    Cheers

    0 讨论(0)
提交回复
热议问题