uxebu / bonsai

BonsaiJS is a graphics library and renderer
http://bonsaijs.org
Other
1.96k stars 189 forks source link

Any chance for AMD support? #209

Open busticated opened 11 years ago

busticated commented 11 years ago

Forgive me if this has already been addressed, just starting out w/ Bonsai. Wondering if you would be open to supporting AMD-style loaders such that Bonsai (and supporting modules) could be loaded via:

define(['path/to/bonsai'], function(bonsai){
    // bonsai!
});

I'm currently using RequireJS' "shim" config option...

Thanks in advance! -matt

klipstein commented 11 years ago

Where do you see the advantage of having AMD support other than not exposing the global bonsai namespace? AMD-support for the src version is already there, but when you load it via RequireJS, you have to decide whether to use the iframe or the worker runner (see an example here: https://github.com/uxebu/bonsai/blob/master/example/library/index.html#L80).

Just the built file will take care to use the right runner (iframe or worker) for you depending on browser features and I assume you want that this file will provide AMD-support?

We are open to add AMD support, if it makes sense and as long as we can still provide our load-logic, where we wrap the whole bonsai-code into a named closure (https://github.com/uxebu/bonsai/blob/master/Makefile#L71) which is fed as blob/data-uri (https://github.com/uxebu/bonsai/blob/master/src/bootstrapper/_build/common.js#L46) to a worker/iframe runner context (fyi: this allows us to concat a bonsai build with other js code).

busticated commented 11 years ago

well, in fairness I am still starting out w/ bonsai here so I sort of don't know what I don't know.. if that makes sense ;-) from what i've seen, it's a really well-thought-out and powerful lib... really great of you all to make it available for others - thanks!

Where do you see the advantage of having AMD support other than not exposing the global bonsai namespace?

in a word, convenience... being able to throw in a dependency to a lib and have it load, execute, and build as appropriate is handy. there are work-arounds of course (requireJS' "shim" config, auto-wrapping via volo.js, etc).

Just the built file will take care to use the right runner (iframe or worker) for you depending on browser features and I assume you want that this file will provide AMD-support?

correct! fwiw, i'm currently using a wrapped version... seems to work fine.

//Wrapped in an outer function to preserve global this
(function (root) { var amdExports; define([], function () { (function () {
    // bonsai!
    amdExports = bonsai;
}.call(root));
    return amdExports;
}); }(this));

...but kind of gnarly :-/

side-note: imho, having a built but unminified version would be helpful as well.

klipstein commented 11 years ago

well, in fairness I am still starting out w/ bonsai here so I sort of don't know what I don't know.. if that makes sense ;-)

Now you know a little bit more :) I mostly tried to explain the complexity of our build-process to myself and recognized that it is not easy to explain :)

correct! fwiw, i'm currently using a wrapped version... seems to work fine.

Thanks for playing around with adding AMD support to the built file. Where exactly did you make that change so I can test it on my end and is the reference to bonsai then the window.bonsai? There is the branch https://github.com/uxebu/bonsai/tree/unify-plugins-and-urls (not in a stable state yet) which tries to simplify our internal JS loader and it probably would be good, if AMD support would be added when that is in, because we also cleaned up the bootstrap-code a lot there.

side-note: imho, having a built but unminified version would be helpful as well.

I know :( We already worked on adding grunt as task-tool to BonsaiJS (https://github.com/uxebu/bonsai/tree/grunt), where we then would use RequireJS for building the release, which would allow us to provide an unminified version. We thought we would be clever and use the ClosureCompiler to resolve the define statements, so we don't have to ship almond or another simple AMD resolver. But using ClosureCompiler prevented us to provide an unminified version and the minification is not as efficient as using RequireJS+Uglify.

I'll take care to look into those two mentioned branches and will play around to expose BonsaiJS as AMD module for the build case. Hopefully next week.

busticated commented 11 years ago

Nice - all of that sounds good to me! :clap: Happy to help test things out when / if you need.

Where exactly did you make that change so I can test it on my end and is the reference to bonsai then the window.bonsai?

I threw my test project into my account... the bonsai lib is over here The wrapping is just what volo.js provides out of the box. One of these options may be more appropriate longer-term. And, yes, bonsai === window.bonsai

StrictlySkyler commented 11 years ago

One place which would benefit from the AMD pattern (or CJS, or anything else, really), is the ability to update the stage with new methods after the worker has been initialized.

For example, rather than having a single monolithic function containing all of the code to execute as a movie, I'd like to be able to split the methods into separate files, and be able to update them dynamically based on user interaction. One file would contain the logic for drawing and updating paths, for example, while another would contain closed-path polygons, and a third might allow the user to define a custom method by which to generate a shape they desire.

Thanks!

basecode commented 11 years ago

For example, rather than having a single monolithic function containing all of the code to execute as a movie, I'd like to be able to split the methods into separate files, […]

+1

[…] a third might allow the user to define a custom method by which to generate a shape they desire.

In case I got you right, I think it's sufficient to have one module that contains the logic for drawing and updating paths on the renderer side. On the runner side Bonsai allows you to write plugins (which are modules as well) that can extend Bonsai's Path API.

Runner (worker, iFrame, server) Renderer (SVG, DOM, Canvas, WebGL)
Path PathRenderObject
MyOwnPolygonPath PathRenderObject

Which means, whatever Path plugin you're going to write, on the renderer side the path is always drawn by the same PathRenderObject. That works because the runner sends a "normalized" data-structure to the renderer.

StrictlySkyler commented 11 years ago

I'll look into the Path API, thanks for that.

The goal here, in the end state, is to allow the user to write code for custom rendering, such as shapes, schematics, and graphs for data visualization, and allow them to import it dynamically into the existing stage.

The worker method importScripts() can do some of this, but communicating with it can be something of a chore.

Thanks again.