componentjs / builder.js Goto Github PK
View Code? Open in Web Editor NEWv0.x of the builder. v1.0.0+ is located at:
Home Page: https://github.com/component/builder2.js
v0.x of the builder. v1.0.0+ is located at:
Home Page: https://github.com/component/builder2.js
I'm really enjoying using component, but I've run into a problem trying to inject some configuration data. When I try to use addFile it throws because apparently this.conf is undefined. I don't quite grok where conf comes from.
Here's an easy way to reproduce the problem.
// test.js
var Builder = require('component-builder');
function test(data, cb) {
var builder = new Builder(data);
// vvv throws
builder.addFile('scripts', 'file.js', 'var foo = 0;');
builder.build(function (err, obj) {
if (err) {
return cb(err);
}
cb(null, obj.require + obj.js);
});
}
test('.', function (err, obj) { console.log(obj); });
Am I using addFile incorrectly? Any hints on how to inject configuration data during runtime?
Not 100% sure what's going on here, but basically it looks like the aliasing is a bit off.
If you include component/model
as a development dependency we get duplicates:
require.alias("component-model/lib/index.js", "collection/deps/model/lib/index.js");
require.alias("component-model/lib/static.js", "collection/deps/model/lib/static.js");
require.alias("component-model/lib/proto.js", "collection/deps/model/lib/proto.js");
require.alias("component-model/lib/index.js", "collection/deps/model/index.js");
And var model = require('component-model')
does not work in test files:
Uncaught Error: failed to require "component-model" from "root"
The first time Builder.prototype.buildType
method is run it is for 'scripts' and an async request for the component.json config request is made. Then Builder.prototype.buildType
is run again for 'styles'. The callback for the first request has not returned, and therefore not been cached, so a second request is made for the component.json is made.
This is problematic, as it is possible that two completely different instances of the configuration could be floating around.
I believe this to be cause of a problem I had doing async stuff inside a 'styles' hook. I hope I have got this right.
This gist shows an example:
https://gist.github.com/4556128
to facilitate building of ./component.json with deps in ./components
Any thoughts on the ability to wrap the output of a build type prior to having the final result?
Couple uses cases:
Suppose our app's "boot" component started things off with pet / user listings,
we might have a simulated fs like this:
./user
./deps
./inherit -> component-inherit
./animal
./deps
./inherit -> component-inherit
./component-inherit
./pet-list
./deps
./pet -> pet
./user-list
./deps
./user -> user
./boot
./deps
./pet-list -> pets-list
./user-list -> pets-list
Now for the sake of argument if "component/inherit" was used for animal, and "learnboost/inherit" was used for user it would simply resolve like this:
./user
./deps
./inherit -> learnboost-inherit
./animal
./deps
./inherit -> component-inherit
./component-inherit
./learnboost-inherit
./pet-list
./deps
./pet -> pet
./user-list
./deps
./user -> user
./boot
./deps
./pet-list -> pets-list
./user-list -> pets-list
Effectively every dependency is "linked" to a root-level canonicalized component name / module definition. App-specific components such as say ./signup
should work out of the box without collision from any public deps since it's not namespaced by a GH account
for component build --dev
I have some paths
and locals
in my root component.json
and when I try running it outside of the directory that contains that file, I end up with:
Error: failed to lookup "app"'s dependency "necolas-normalize.css"
I think it has something to do with this piece in Builder.prototype.lookup
:
if (!path) return fn(new Error('failed to lookup "' + self.name + '"\'s dependency "' + name + '"'));
var dir = join(path, name);
fs.exists(dir, function(yes){
if (!yes) return next();
debug('found %s', dir);
fn(null, dir);
});
dir
is relative, so I fixed that by adding dir = self.path(dir)
, but then I end up with:
Error: failed to lookup "visionmedia-superagent"'s dependency "component-emitter"
.. which is an improvement (first dependency that contains it's own dependencies). But yah - not really sure what's going on here, haha.
sync for loading in template files etc is not ideal
If you require a library like moment
which I now have a component-comptible verison of at ForbesLindesay/moment
from outside any component, it can go badly. eg.
<script src="build/build.js"></script>
<script>
var moment = require('ForbesLindesay-moment');//this doesn't work
var moment = require('ForbesLindesay-moment/moment.js');//this must be used instead
</script>
Also, should we lower-case all names at some point, not sure where's best to do that?
Currently the build tool aliases the entry component (the one being built) but doesn't do it for others. This makes things a bit inconsistent either all modules should be available globally or none.
Example:
require.register("jkroso-emitter/src/index.js", ...)
can't be required from the console using
require('jkroso-emitter')
Instead I would need to use
require('jkroso-emitter/src')
i have a complex directory structure:
├── build
│ └── build.js
├── component.json
└── modules
├── login
│ └── bar
│ ├── History.md
│ ├── Makefile
│ ├── Readme.md
│ ├── bar.css
│ ├── component.json
│ └── index.js
└── signup
└── foo
├── History.md
├── Makefile
├── Readme.md
├── component.json
└── index.js
"paths": ["modules/*/"]
if we have 50 components requiring "bar", then bar/component.json is attempted N times.. this sucks, we need a locking mechanism this is really wasteful
Weird, I think the most recent builder.js
has been published, but the repo hasn't been updated. I'm seeing buildAliases
in the published version, but nothing about aliases here.
It would make for much better efficiency if we had a good system for somehow minifying the path names in the built output. Things like UglifyJS don't do a great job of minifying the names of things in the output of builder.js. There's not a lot you can do when it's not standalone, but when it is, we could minify all path names to a few characters if we're clever.
There is a composability issue with the ´local´ functionality: if a component has a local dependency which in turn has a local dependency, the top level ´component build´ fails.
moar wasted
when it's specified in the component.json files, if we even keep this, move from component-build(1)
add a little helper to keep track of which have been added already, just less crap output
https://github.com/component/builder.js/blob/master/lib/builder.js#L796
Private components may facilitate urls relative to host. It's better to write
return ~url.indexOf('://') || url[0] == '/';
Modules are wrapped to wrapper and registered via this currently
require.register("module/path", function(module, exports, require) {
// js
})
but it will be cooler to conform to spec http://wiki.commonjs.org/wiki/Modules/Transport/D. The result should be like this
require.define({"module/path": function(exports, require, module) {
// js
}});
Note passing an object instead of just string & fn.
currently we assume the components were installed and thus have the correct name but this may not always be the case, it would be safer to generate aliases based on repo
very dependent on the fs, so we need to organize these better it's a bit unwieldy currently, mostly because the names make no sense. also add tests back for lookup paths, whoever initially wrote those used some files from ./examples for the tests, so when i removed those examples it broke
window.data-table = require("data-table");
Should either be:
window['data-table'] = require("data-table");
or
window.dataTable = require("data-table");
The later nicely follows the same conventions as element.dataSet
so I'd support that one, but I don't mind.
There's one try-catch that should be on the json.parse only, now it returns in the try block and thus eats silently the errors thrown later in the build chain (as in the examples, for example).
Somewhere in https://github.com/component/builder.js/blob/master/lib/builder.js#L339-343, it's using the wrong component name for the alias. I was trying to make a simple app with my component stuff living in a folder called "static". I named my main app component "app".
See this gist for my files and the generated build.js https://gist.github.com/43927d6c31d83372a7c8
The last line in the build is in error. It's using the folder name for the component name instead of the specified name in the component.json.
or the nicer "bundled" suggested by G, "devDependencies" == "dev" as well?
for example like how we build on-demand per request in development
~300ms for popover right now, too slow
swear we had an issue for this already, for example lib/calendar.js fails to require('jquery'). note to self: fix calendar
If we add in the following alias here:
batch.push(function (done) {
var main = self.conf.main || 'index.js';
//todo: special case root for self.name to use self.conf.name instead
done(null, 'require.alias("' + self.name + '/' + main+ '", "' + self.name + '");\n');
});
And change our aliasing here to:
var js = 'require.alias("' + builder.name + '", "' + alias + '");\n';
And swap the order of aliasing here to:
done(null, str + aliases);
That would make main override the index.js default file name. I really need this, so if those changes would be acceptable then please can we get this sorted?
It should also let us simplify require.resolve
to:
require.resolve = function(path){
var orig = path
, reg = path + '.js'
, regJSON = path + '.json'
, indexJSON = path + '/index.json';
return require.modules[reg] && reg
|| require.modules[regJSON] && regJSON
|| require.modules[indexJSON] && indexJSON
|| require.modules[orig] && orig
|| null;
};
for example auto-compiling your private component's Jade / Stylus files etc. I dont want to provide stupid plugin apis for this, just an extremely simple API so that you can add stuff to the build files before completion
Lets say I have 7 local modules depending on "xyz/backbone" and then want to switch over to "component/backbone".
Currently, I'll have to change this in 7 places. Since it mostly should be the case that all local modules should depend on the same backbone-module, it would be preferable if the namespace was inferred from the main component.json.
could create test/ folder with a make task for it, or maybe let the user chose to run tests on the browser. would imply mocha ?
Some backends (... django) just don't work with symlinks.
very unlikely to clash
Because we take all the scripts when doing aliasing here we are creating lots of aliases that don't actually work anyway. We end up directing all those files to the index.js file anyway, so it's redundant. This could alow us to change things to:
var aliases = (function () {
var name = builder.conf.name;
// TODO: remove special-casing root
var alias = self.root ?
self.conf.name + '/deps/' + name
: self.name + '/deps/' + name;
var js = 'require.alias("' + builder.name + '/index.js", "' + alias + '");\n';
return js;
}());
This will simplify our move to not hard-code index.js
for example a dev dep of the following is added:
require.alias("visionmedia-superagent/lib/client.js", "model/deps/superagent/index.js");
which is fine for the model deps but we also need:
require.alias("visionmedia-superagent/lib/client.js", "visionmedia-superagent/index.js");
When writing a component with a single script in "scripts", it feels unnecessary to add a "main" directive to point to it.
If I have:
"dependencies": {
"component/jquery" : "*",
"matthewmueller/emitter@patch-1" : "*"
}
I can install the right deps but I cannot build.
so json
/ json-polyfill
can work
Been running into this issue most the afternoon. I've been using a version of the component build middleware in the component.io repo. Server dies every 2nd request, perhaps a clean-up issue.
Probably have about 40 components. Anyone else running into this?
It doesn't include the dependencies or locals the second time around.
Just for context: writing a quick middleware component and reinitializing Builder
every time causes a lot of duplicate effort. Also, exec('make')
ends up being pretty slow for bigger apps.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.