cujojs / curl

curl.js is small, fast, extensible module loader that handles AMD, CommonJS Modules/1.1, CSS, HTML/text, and legacy scripts.
https://github.com/cujojs/curl/wiki
Other
1.89k stars 216 forks source link

Optional "rewrite" function for custom path behaviors #135

Closed asilvas closed 11 years ago

asilvas commented 11 years ago

I've got a situation where:

  1. Short paths are already being used in a production setting (i.e. "shortpath/mod1" is rewritten as "verylongpath/mod1/mod1" via "paths" object).
  2. The shortpaths used do not correspond to the folder structure - Example: "shortpath/mod1" corresponds to "verylongpath/mod1/mod1", so using a path option of "shortpath/": "verylongpath/" is not an option.
  3. There are MANY modules... Unrealistic to define all of them via "paths" (including their corresponding "css!").
  4. Dozens of apps and possibly thousands of uses using the above schema already, and wish to retain backwards compatibility rather than forcing dozens of devs to update their code.

I'm trying to avoid directly modifying the curl loader, as it could slow the inclusion of new builds in the future.

Any chance a custom "rewrite" function could be included for custom pathing behaviors? This would be very powerful (with very minimal code footprint), and likely avoid future needs of smarter "path" options, as you don't get much more custom than a callback.

Example:

curl = {
  rewrite: function(url) {
    return url; // or do something custom with it
  }
}

Appreciate any ideas, or inclusion of such a function.

asilvas commented 11 years ago

Also, leveraging a "plugin" to create this behavior (i.e. "rewrite!mod", "rewrite!css!mod.css") is not an option, as that too would break compatibility.

unscriptable commented 11 years ago

This is an interesting concept. I've got a few ideas.

How do you feel about using a preloaded shim? I've been planning to finalize curl's "internal" API and how it's exposed. Right now, you have to do something similar to the code in #133, but we could make a formal API, something like `define(["curl/api"], function (api) {}); and start putting stable functions onto it.

asilvas commented 11 years ago

That would be perfect. Will #133 example allow me to achieve this result in the mean time? I'd be ok with having to update the shim later as I can control that on the build side. My main requirement is that it is reliable, and not conditional; in other words, I can always intercept the path and update it no matter what.

unscriptable commented 11 years ago

Yes, you can use the technique in #133 for now. Note, however, that the function you probably want to override, resolvePathInfo, is somewhat likely to change between now and 0.7.2.

// curlshims/rewrite
define(['curl/_privileged'], function (priv) {
    var resolvePathInfo = priv.core.resolvePathInfo;
    // absId is the id of the module to fetch
    // cfg is just the global configuration object if you're not using packages
    priv.core.resolvePathInfo = function (absId, cfg) {
        // do something pathy here or just return the usual result:
        return resolvePathInfo.apply(this, arguments);
    };
});

Here's the current resolvePathInfo. Note it returns both the url and a package-specific config object. Since you're not using packages, this will always be the global config object (userCfg).

        resolvePathInfo: function (absId, cfg) {
            // searches through the configured path mappings and packages
            var pathMap, pathInfo, path, pkgCfg;

            pathMap = cfg.pathMap;

            if (!absUrlRx.test(absId)) {
                path = absId.replace(cfg.pathRx, function (match) {
                    pathInfo = pathMap[match] || {};
                    pkgCfg = pathInfo.config;
                    return pathInfo.path || '';
                });
            }
            else {
                path = absId;
            }

            return {
                config: pkgCfg || userCfg,
                url: core.resolveUrl(path, cfg)
            };
        },

Just FYI, you can call curl(newConfig) multiple times now. It does its best to merge the new configuration onto the old one. It doesn't warn you if you're overwriting baseUrl or other things that probably shouldn't change. However, you can add new paths, etc. iirc, you were looking for this feature. ??

-- John

asilvas commented 11 years ago

Awesome, much appreciated. I understand it is likely to break in future builds, but so long as I have a way to fix it (until a more concrete option is available) that is no problem.

Regarding the applying of configs multiple times, since the original design had to drop that feature, it may not be overly critical anymore. However, being I'm in the middle of a bit of a refactor, I will most certainly keep it in mind, it might come in handy.

Thanks again! I'll close the issue once confirmed.