-
Notifications
You must be signed in to change notification settings - Fork 79
Proposal: Ender package.json extensions #131
Comments
I swear you just read my mind. For personal clarity does glob matching pattern mean something similar to How would Proposal 2.3 affect the 4th current use? Main is what would be called in via npm’s require('module') and the ender+dependencies key for usage in the browser side? Concerning proposal 3—my fork playing with this approach requires redownloading everything from npm every build—even when the version is locked and locally available. Will other changes using npm itself to manage dependencies help resolve this unnecessary roundtrip? What is your opinion of adding an array of objects under the |
Thanks for the feedback @iamdustan, good to have someone else engaged on this. Glob matching is just a simple pattern matching mechanism usually used for matching files and directories. It used to be native in Node which was a problem cause Window doesn't have a proper native implementation that matches the *NIX's, but now we have node-glob which uses minimatch internally to translate the patterns to regexes. The basic units of matching would be Regarding 2.3, there's a error in my original that has npm bugs me, if you run an As for an array of |
I'm starting to think that overriding dependencies with ender->dependencies perhaps isn't a great idea. The main problem is that we can't stop npm from installing dependencies of any package we ask for, it'll just do it. We could try and get that patched but there are other problems, npm does a build if one is defined in the package, usually builds require dependencies which is one reason they are fairly important. So if we stop dependencies then we stop builds, but perhaps you want a build to take place to get the Ender JS set up? So there are a couple of options, we could 'override' in the sense that Ender will still get npm to do its normal thing and install the dependencies it wants but then Ender will install any additional dependencies it needs that come from the ender->dependencies key. So you're doubling up. Then, if you install a package that's meant for both server and Ender you'll do a build and fetch dependencies for the server component even if you just want it for Ender; pretty wasteful. The other option is to not override at all and make the root dependencies key the only way to pull in dependencies for Ender, this would then encourage more of what we have now, that is, packages in npm or client separate from packages for server. So if you have something for server and also Ender then you'd need to publish twice if it was at all complicated, but perhaps that's a good thing. |
I realize the issues involved are far from trivial, but it seems to me that it would be quite useful to be able to optionally split out dependencies appropriate for an ender-build from those that are appropriate for server-side usage. A real-world example: Suppose I'm writing a connector for a database's REST interface (I am actually). For use in the browser, I may want to Near the top of my library I'd probably have something like this: isNodeJS = Boolean process?.pid
if isNodeJS
request = require 'request'
else
request = require 'browser-request' But how to deal with the divergence with respect to ender and Is that ideal, though? It seems like it would be better if I could publish a single package and split apart the dependency groupings within the one |
That's precisely one of the use-cases I'm thinking about and it'd be great to handle this nicely. My only issue at the moment, as per my previous comment, is that we can't stop npm from installing request if it's listed as a "dependency" even if it's not needed for the Ender build. That may not be a big issue for your use-case, but consider socket.io-client which has a dependency tree that looks like this:
and ws requires a compile step. Ideally you should be able to But perhaps it's good enough to point these problems out to module authors and let them deal with the flack they'll likely get from this? |
Personally, I don't think installing the node dependencies is a big issue. In fact, given ender's dependence on NPM, I don't see a way around it. If the module is designed to work on both the client and the server, I don't see how NPM could easily distinguish a module in This issue of not being able to specify different dependencies for client/server packages has been really biting me lately, so I'd like to help implement these extensions. |
I'd also like to suggest the possibility of having a |
Great to have you on board with this one Andrew. Check out the 1.0-wip branch, I don't think the current master is going to see any significant work now. Unless someone finds it handy for experimentation of course but the new code should be easier to hack if you can get your head around it and keep the tests happy. |
as per #57, @coolaj86 points to the "overlay" property in the Modules spec: http://wiki.commonjs.org/wiki/Packages/1.1 |
+1 for the externs option! Fantastic! |
A lot of this is done now with the latest batch of 1.0-wip work, released to npm with the tag dev, so you can "main", "name", "ender", "dependencies" can all be overridden in any package by including them in the "ender" key of package.json (or alternatively the "overlay"->"ender" key as per the CommonJS Packages spec). So a package.json can have: You can also override dependencies in the same way and only the overridden ones will be installed (even though npm will also install the root dependencies--they are just ignored in your build). I'm still missing some functional tests to lock the changes in, plenty of unit tests for this stuff though so it's pretty solid. Also notable in this release is that Ender won't fetch packages from npm that are already installed in node_modules unless you use the |
Sounds fantastic! Thanks for all your hard work. |
How about instead of
|
For pakmanager to use And I believe it would be better to publicly support a single standard (i.e. overlay.browser) rather than two (browser and overlay.browser), but still support the accidental usage for backwards compatibility. |
I'm happy to adopt appropriate aliases if you think that's necessary but I think I'd rather keep the "ender" key because there will be a bunch of very Ender-specific stuff to go in there. The logic for this is done in one place only so it's pretty easy to amend. Perhaps you'd like to put up a PR for discussion? |
I love you. |
😊 |
In the original proposal, the bridge would be overridden with a |
I'll freaking love you hard if that externs thing happens to resolve itself. O:) |
whoa. |
@amccollum I still want to go with the "bridge" key but it's a special case I haven't got to yet. I think it'll just be an alias for "ender" so they will both work. |
Well, I submitted a pull request (#147) to make this work (just with the |
Cool. Sorry, didn't notice the PR. Will take a look ASAP, thanks! |
@andrewplummer that The package.json Because overriding is now in action, your I have unit tests for internal functionality but functional tests are a bit trickier so I'd appreciate it if you were able to test this (with Sugar I guess?). A package in npm that has a valid & working You'll need the 1.0-wip branch, either clone the repo or |
Cool! Will do! |
@rvagg and to think you’ve been so quite lately and then you come out with this. Word. |
Hey... I had a bash at it but didn't have any luck... not sure the version is right though. I cloned the repo and set to
So on a whim I copied my version of the compiler to that file then compiled again. Compiled, but the externs weren't applied apparently. However, running |
I should have mentioned that this is now working on When you run If you want to see the actual Closure command then edit node_modules/ender-minify/lib/closure.js and Since we're not reading anything from dependencies in |
Oh... well if that's the case, then I think it's already working... I tried loading the Unfortunately (for testing this anyway), |
Ah wait... I just flashed on something... are you saying that if you don't specify |
Yes, UglifyJS is the default |
Ahh ok...well that would do it :) Well funny... I build it and even without the externs file it seems to work... It's good news but I'm still not sure what to make of it .... |
I'd like to propose that The main argument against this proposal is that it requires some repetition and additional verbosity in the package.json file. There isn't really a difference in speed since we install all the same modules either way. Of course, Ender can emit an error if it finds that this rule is being broken. Do others have thoughts about the benefits or drawbacks of enforcing this requirement? |
I'm fine with this btw, it has added a fair bit of complexity to support a totally separate list and reducing complexity is always a good thing. |
This is really good stuff. If anyone else is also waiting for the ability to specify the output location in package.json, and you also use Grunt, I created a Grunt plugin to help with this problem (until the real solution is in place). |
+1 for grunt-ender |
I'd like some feedback on extending package.json for additional flexibility.
Current package.json uses
Also possible:
Proposals
"main"
and"ender"
keys accept any of:"ender"
key to allow for the following sub-keys:"bridge"
to represent the bridge file(s) in the same way as a string/array"ender"
key would"dependencies"
of the same format as the root"dependencies"
key, the existence of ender->dependencies tells Ender to ignore the root key and install the dependencies listed here. A package may be usable in both Node and Ender and have different dependencies for each."main"
to override the root"main"
key where present. Useful for a package that works in both Node and Ender."ender"
key for use with a no-argender build
in the same directory as the package.json. The descriptor then becomes a build command, replacing all additionalender build
arguments. Optional of course, the commandline will still work as normal."dependencies"
becomes the packages that you would normally specify on the commandline."bridge"
becomes simply a way to add"noop"
, any other value is ignored; replacing--noop
."sandbox"
can be either a boolean or an array of package names. A"true"
will indicate that the whole build should be sandboxed but that none of the packages should be exposed onwindow
. An array of package names will indicate that each of those packages should be exposed onwindow
; replacing--sandbox [<package>...]
"output"
indicates where the build should be written. It should be without a .js suffix but that will be stripped if included anyway. Can include a relative or absolute path or just a local filename (.js and .min.js will come out). Replaces--output
."compile"
will include the additionalender compile
step in the build process, running your build through Closure Compiler with any additional files. Can be any of:"true"
will just run Closure over the plain ender.js."files"
key which contains an array of files to include in the build after ender.js."output"
key specifying where the resulting compile should go (same rules as ender->output)."externs"
key which contains an array of files to pass to Closure as--externs
arguments.Examples
1. A package that can be used as both a Node package via
npm install
and in an Ender build viaender build/add
."main"
descriptors are different for each case, as are Dependencies.2. A local package.json that will be read on a plain
ender build
orender build <x>
where x points to the directory containing this package.json.Would result in the same as the following commands:
You would end up with foobar.js, foobar-min.js and foobar-app.js in your dist/ directory.
Notes
All
"main"
files will be simply concatenated for inclusion in a build, as long as the build isn't--noop
the whole lot will also be wrapped in anexports
capturing block. All"ender"
files, where present, will then be concatenated for inclusion after the"main"
files.npm is responsible for installing all dependencies from the core package lists all the way down. Introducing an ender->dependencies key means the Ender CLI would have to loop back and install any missing dependencies that npm isn't aware of. Additionally, npm will install unnecessary dependencies from the root
--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/742651-proposal-ender-package-json-extensions?utm_campaign=plugin&utm_content=tracker%2F165667&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F165667&utm_medium=issues&utm_source=github)."dependencies"
key, which would be undesireable--such as when there are lots of unnecessary dependencies and/or dependencies that take lots of extra time to download and/or install (compile perhaps). Ideally we could subvert npm's dependency management process.The text was updated successfully, but these errors were encountered: