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

support fromText in plugins #115

Closed johlrogge closed 11 years ago

johlrogge commented 11 years ago

RequireJS adds a fromText to the load (or callback) argument to a plugins load-method. The functionality is described like this:

Some plugins may need to evaluate some JavaScript that was retrieved as text. To evaluate the JavaScript correctly, particularly if it contains require() or define() calls, there is a function off the load() argument, load.fromText(), that can be used to evaluate the JavaScript. eval() is used by RequireJS to evaluate that JavaScript.

Arguments for load.fromText():

name: String. The name of the module being loaded. Useful for anonymous module calls. Always pass a value. You can use the file path that was used to retrieve the text if there is no matching module name for the text.

text: String. The string of JavaScript to evaluate..

For full information here:

http://requirejs.org/docs/plugins.html#apiload

This is very useful for making "interpreter-plugins" like https://github.com/jrburke/require-cs

I am personally trying to make a curl-plugin that interprets modules written in sibilant http://sibilantjs.info/#welcome in the same manner as require-cs but it is a little bit tricky to get the last step running. (the sibilant module I'm trying to interpret is a full fledged AMD-module and I now have it automatically translated to javascript "in memory", my last step would be to use load.fromText to have curl take my javascript from a string rather than a url...)

unscriptable commented 11 years ago

Hey @johlrogge!

Nice work on SibiliantJS! Transpiling to JavaScript and/or AMD is one of the things I'd like to do more with curl.js!

Take a look at the curl/loader/cjsm11 module. It converts to AMD from CJSM/1.1. It does this without a special API call on any of the load method's callbacks. It simply ensures that the text includes a named define() and evals the text (or injects it as a script element).

The code to eval and/or inject the JavaScript is only 10 lines of code. Still, I think it makes sense to put it somewhere DRY. What if I create a curl/eval module for evaluating/injecting scripts? This module can be shared by cjsm11 or any of the other "transpiling" modules.

Regards,

-- John

johlrogge commented 11 years ago

Thanks John, I'll look into that tonight.

As much as I'd like to take credit for sibilantJS I'm just studying it to see if it does what I want. In the process of that I'm looking into how well it plays with AMD and half hoping that my fiddling will amount to something useful for someone else. I would like to have a fast feedbackcycle for exploratory development in the browser, benefit from AMD and be able to write production performance clientside stuff. Curl.js + cram + plugins seems to give me all of that with zero drawback (apart from having to write a plugin but that is just fun :))

I'll comment about my progress and share my code on github later. If I'm successful we will know more what the module should look like. It sounds like a great idea!

Cheers!

unscriptable commented 11 years ago

We also have a google group now. This topic sounds like it could benefit from discussion amongst cujo-ers. :) -- J

https://groups.google.com/d/forum/cujojs

On Wed, Aug 1, 2012 at 10:13 AM, Joakim Ohlrogge < reply@reply.github.com

wrote:

Thanks John, I'll look into that tonight.

As much as I'd like to take credit for sibilantJS I'm just studying it to see if it does what I want. In the process of that I'm looking into how well it plays with AMD and half hoping that my fiddling will amount to something useful for someone else. I would like to have a fast feedbackcycle for exploratory development in the browser, benefit from AMD and be able to write production performance clientside stuff. Curl.js + cram + plugins seems to give me all of that with zero drawback (apart from having to write a plugin but that is just fun :))

I'll comment about my progress and share my code on github later. If I'm successful we will know more what the module should look like. It sounds like a great idea!

Cheers!


Reply to this email directly or view it on GitHub: https://github.com/cujojs/curl/issues/115#issuecomment-7428338

johlrogge commented 11 years ago

I finally managed to get it to work (somewhat). I'm going for the globalEval approach (turns out that is what I have been doing all along). My remaining problem: my module sibilant code translates to an anonymous module.

define([], function(){...})

When I evaluate it it is evaluated under "plugin!module-name" (that is my guess). So when I want to fetch the value with loaded(require("module-name")) I get "module not resolved".

If I hardcode a module-name in my sibilant module like define("hardcoded", [], function() {...})

and use loaded(require("hardcoded")) it works.

It would be nice though to be able to decide under which name an anonymous module is evaluated in some way.. like priv.core.context(resourceId, function() {globalEval(source)});

I'm sure there is a way, I could use some pointers though :)

Really tired now so I'm to stupid to figure it out myself ATM.

Suggestions?

unscriptable commented 11 years ago

Ah, yes. If you're using "plugin!moduleId" to request the module, that's how it will be cached. The cjsm11 loader module is meant to be used as an implicit plugin (see #24). You specify an implicit plugin like this:

packages: [
    { name: 'mypkg', location: 'lib/ver/mypkg', main: 'whatevs', 
        config: { moduleLoader: 'curl/loader/cjsm11' }
    } 
]

This tells curl to apply the cjsm11 plugin to all modules in the package, "mypkg". Therefore, you don't specify them as "cjsm11!mypkg/mymodule", you just specify them as "mypkg/mymodule". Note: the word, "moduleLoader" is temporary and will be changed in curl.js 0.8. Also: moduleLoaders and plugins probably don't work together. If your package uses text! or css! plugins (for instance), this may not be the solution for you.

If you wish to keep specifying modules using "plugin!moduleId", then change your code to inject "plugin!moduleId" into the define().

Did you notice the injectScript config option? That can be handy for debugging in IE 6-8, btw.

Please paste your code into a gist (public or private) so I can see it.

Lastly, I am on #cujojs on freenode quite often lately and we have a new google discussion group: https://groups.google.com/d/forum/cujojs I think lots of people would like to see what you're doing with sibilant. :)

-- John

johlrogge commented 11 years ago

I got the plugin to work now. I think it will work both as a loader and a plugin but I have to verify. I will figure out how to wrap it up (right now I coded it in a fork of sibilant and I think it would probably work better as an optional plugin). Once I have decided I will share the code on github soon so that everyone that is interested can have a look/fork/comment. I will post to the cujojs group when ready :)

unscriptable commented 11 years ago

nice! I can't wait to see it!

johlrogge commented 11 years ago

Applied for the group and pushed the sibilant plugin here: https://github.com/johlrogge/sibilant/tree/feature/npm-plugin

It is a fork from sibilant so everything is in the repo to run it.

It is precompiled in the lib-directory and an example that logs hello world is setup in the 'browser' directory

to recompile:

npm link
sibilant src/*.sibilant -o lib

The relevant source is in src/sib.sibilant (the plugin) and include/amd.sibilant (some macros for writing modules) and test/amd.sibilant (tests for the macros)

It is all pretty ugly. No cleanup made just happy it works :)

unscriptable commented 11 years ago

Ha! lol. it's a copy-and-paste-and-sibilant-ification of the cjsm11 module! :) (https://github.com/johlrogge/sibilant/blob/feature/npm-plugin/src/sib.sibilant)

For some reason, I expected you were going to write the plugin in javascript. silly me. :)

Interesting to see how it transpiled it: https://github.com/johlrogge/sibilant/blob/feature/npm-plugin/src/sib.sibilant

You've inspired me to extract the reusable bits from the cjsm11 module so ppl will be able to create these easier!

-- John

johlrogge commented 11 years ago

Oh no, I'm busted :) I had to make it more fun. It would be good to be able to just depend on the reusable parts :)

unscriptable commented 11 years ago

This will get easier in 0.8 when we introduce "module transforms". Closing for now. Keep watching for 0.8!