componentjs / builder2.js

builder for component
50 stars 20 forks source link

How can a plugin add additional files to the build? #45

Open dominicbarnes opened 10 years ago

dominicbarnes commented 10 years ago

I'm working on a plugin that creates an image sprite out of a series of image files. In the old version of component, I accomplished this in a really hacky way that I'd like to avoid.

When I say "hacky", I mean I had to do 2 things. First, I generated the relevant CSS and injected it via builder.addFile. Then, I generated the image in a temp directory, then copied it to where it "should" be. (ie: calculated the destination based on what are likely internal APIs/properties)

Right now, my component.json files look like: (I'm open to changing this to make things easier)

{
    "name": "something",
    "sprite": [
        "images/*"
    ]
}

The end-result is a sprite.png and sprite.css that are added to this particular component's manifest. In this new builder, is there any way that a plugin can add/remove files in the build itself?

jonathanong commented 10 years ago

what i would actually do is do all this before passing the tree to the builder.

var tree = yield* resolve();

// probably flattening the tree and searching by name or field
var spritenode = findSpriteNode(tree);

// do whatever you want to the node
spritenode.node.images = []
spritenode.node.styles = []

// actually pass it to the builder
build.styles(tree, function (err, js) {})

does that make sense?

jonathanong commented 10 years ago

in other words, why does this have to be component plugin at all? i personally would just do it in a single JS file. no need to make it a plugin. unless you're doing it multiple times, but then i would just make it lib-ish.

dominicbarnes commented 10 years ago

Well, any local component in my app could have a sprite. Would I need to generate those artifacts and drop them in place for each component? That seems even more hacky than before, is there not an addFile counterpart?

dominicbarnes commented 10 years ago

Any chance we could extend component-manifest to give further capabilities beyond just read for files. (such as add and remove?)

jonathanong commented 10 years ago

this builder only does per-file, 1-to-1 transforms. you would have to alter the nodes on the tree, which is what the old builder did.

i'm not sure if adding stuff to component-manifest would work. can't think of an easy way to do this off the top of my head other than transforming the tree.

dominicbarnes commented 10 years ago

Ouch, I was really hoping that this limitation (component/builder.js#160) would have been overcome. I really think other plugins could benefit from something like this, I'll keep looking around.

dominicbarnes commented 10 years ago

Since various parts of the build (eg: scripts, styles, files) can be triggered all in parallel, this would be really impossible to manage. I guess I'll have to do the "old-school" thing and just generate those files prior to building. (I'd rather not have the component.json out of sync with files in the directory, just seems like that would be confusing)

jonathanong commented 10 years ago

yeah... non 1-to-1 transforms are used much less often so i didn't want to bother with them. this is always going to be complicated.

bergie commented 10 years ago

Optimally, builder plugins would still be able to add/remove/rename files in the build. This would help us a lot with NoFlo.

Old builder.js had this capability, but it had bugs and my fix hasn't yet been merged component/builder.js#125

jonathanong commented 10 years ago

that's not the job of the builder IMO. the builder should only build files that are already in the manifest.

you're free to use the JS API to manipulate the component.jsons objects prior to passing it to the builder. that's how i suggest you do it.

bergie commented 10 years ago

@jonathanong ah, I see. So, something between the resolver and the builder would (for example) see the scripts lists of the manifests for .coffee files, and move them into another list with .js suffixes? And then we'd run the coffee compiler against that list?

jonathanong commented 10 years ago

yeah. that's what i do. no need for an API for that

jasonkuhrt commented 10 years ago

Running into this issue as well. I am trying to create a plugin that allows NODE_ENV=foo to be exposed in build as require('env') === 'foo'.

I'll try some of the "solutions" mentioned throughout.