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.88k stars 216 forks source link

Implied plugins. Take 2 #71

Closed unscriptable closed 12 years ago

unscriptable commented 12 years ago

It'd be awesome if we didn't have to specify a plugin prefix for non-module resources:

define(['my/widget/ctrlr', 'my/widget/structure.css', 'my/widget/template.html', 'legacy.js!exports=$'], 
    function (ctrlr, css, template, $) {
        // do widgety stuff here
    }
);

The association of file extensions (or other character patterns) can be configured:

curl({
    ".js": "js!",
    ".css": "css!",
    ".html": "text!",
    /mustache-templates\/.*/: "js!", // regex
    "": "my-custom-plugin!", // blank key means any module/resource
    /cdn\.google\.com/: "" // blank value meansdon't use a plugin
});

Specificity should work just like paths work today: the more slashes (/), the higher the specificity. Strings will get converted to regexes by the following formula to help avoid false positives:

rx = new RegExp(pattern + "($|[?!])");

Each package could override the mappings in it's own config.

There's an added bonus to this. Custom module loaders can use the same mechanism.

We'll have to figure out a way to prevent an endless cycle, though, in cases in which the dev is using a plugin that uses require to load its resources. (For instance, a plugin that checks localStorage before fetching from the server would likely just call require for any resources not locally cached.) One option might be for the plugin to place an asterisk or exclamation mark somewhere in the module id before requireing it. curl.js would have logic to avoid the implied plugin code. This seems a bit flaky....hm....

SimplGy commented 12 years ago

This would be a nice little sugar cube. Not so much to save the typing, but to save the forgetting-to-add-the-prefix.

unscriptable commented 12 years ago

It would also allow different packages to use different plugins even if they're named the same. (Not all css! plugins work exactly the same.)

gamtiq commented 12 years ago

+1 for this feature.

briancavalier commented 12 years ago

+1 This sounds great. Maybe drop the "!" on the right hand side? Or do you think it's more intuitive if devs have to include it?

unscriptable commented 12 years ago

@briancavalier plugin-specific paths already use the "!" to help distinguish them. For instance, a path of "js!" targets anything using the js! plugin, but "js" targets anything in the "js/" path. I figured I'd make it consistent with paths. After implementing it, if it's clear it's not going to confuse anyone, we can decide whether to drop the "!".

unscriptable commented 12 years ago

Hm. node matches extensions to its module loader/compilers by including an initial dot:

".cs" -> coffeescript ".js" -> javascript ".node" -> (what a .node file, anyways? :) )

briancavalier commented 12 years ago

Interesting. Is the right hand side here a plugin path? If so, then it def makes sense to go for consistency with other plugin paths.

asilvas commented 12 years ago

Would the idea be that plugin-based paths are additive to existing paths? In other words, more than one path could actually match?

curl({ ".js": "js!", "shortcut.js": "//domain/path.js" }, ["shortcut.js"]);

Would the final path equate to "js!//domain/path.js", "//domain/path.js", or "js!baseUrl/shortcut.js" ?

Trying to wrap my head around the edge cases and possible breaking changes.

asilvas commented 12 years ago

Another thought is, what if I wanted my modules to end in ".js" (which at the file level, they do), this could be a potential conflict?

unscriptable commented 12 years ago

@silvas: good points. At this point in time, I'm trying to collect ideas. I think it's workable without breaking anything, but it needs a bit more thought.

SimplGy commented 12 years ago

On decisions like this it's often good to optimize based on commonality. If you could make the defaults mindless for simple end users like me for the common use cases, you'll be making a big improvement, I think.

Common use cases (for me) that currently require a !plugin:

If these prefixes were eliminated for common use cases the loading library would seem much less like I was doing something naughty and hacky, and more like I was using it exactly as intended.

unscriptable commented 12 years ago

Closing this since a new feature, "module transforms", coming to curl.js 0.8 will offer similar capability.