Skip to content
This repository has been archived by the owner on Jun 15, 2021. It is now read-only.

New way to handle packaging #181

Open
amccollum opened this issue Aug 13, 2013 · 61 comments
Open

New way to handle packaging #181

amccollum opened this issue Aug 13, 2013 · 61 comments

Comments

@amccollum
Copy link
Contributor

amccollum commented Aug 13, 2013

Ok, so I've updated my previous changeset that implements a new Module class at runtime. The changes fall across 7 different modules:

  • Ender
  • ender-args-parser
  • ender-builder
  • ender-dependency-graph
  • ender-package-util
  • ender-js
  • ender-commonjs

Each of the above has a new-packaging branch that includes the changes. The changes in most of the modules are fairly minor, with the lion's share of the changes coming in the ender-builder package in ender-js/ender-builder@4439aee

That commit is huge, so I've tried to comment on some of the larger changes inline to explain what's going on.

It's also worth looking at the new ender-commonjs module, which defines the new way packages are created using a Module class at runtime.

Here's a short summary what these changes bring:

  • New Module object at runtime, supporting multi-file modules, internal/relative requires, requiring submodules, and better CommonJS compatibility
  • Separated the CommonJS client lib from the Ender core
  • Broken out assembly process, allowing for more control over the final build, or possibly replacing CommonJS with other package formats
  • However, to better support CommonJS semantics, this change removes support for using an array of files for the main or bridge, the fix being to either use internal requires to mimic this behavior, or force packages to do their own concatenation

I updated all the current tests to work with these changes, but I haven't gotten around to writing tests for the new assemble.js file, yet. This leaves some holes in the test coverage, mainly around the specific content of the final build. It may take me a little while to get around to this, but I wanted to get the rest of the changes out for comment while I finished up the tests. There may be other bugs as well.

@rvagg, I'd love to hear your thoughts in particular, because I know you were a bit skeptical of some of these changes when I submitted them before.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/969742-new-way-to-handle-packaging?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).
@ded
Copy link
Member

ded commented Aug 13, 2013

just about to hit the sack for the evening until I read all these changed. I think the direction is pretty awesome given the stated goals. internal requires has been a feature even I have wanted for a long time.

I think one thing that should remain a goal is to keep the client interface, even if it isn't the default build (eg: the jQuery syntax).

Also, quite a number of popular modules (with old bridges) would have to get updated build processes

@amccollum
Copy link
Contributor Author

Yeah, to be clear, I definitely think the client-interface is integral to Ender, even if technically it can be replaced. Part of what makes Ender great is that it is opinionated about a small number of core decisions, so other modules can build on those common assumptions. Another example of this behavior is that even with the new Module class, we auto-require every module (and bridge file) once on startup, in case modules modify the global context or need to do other initialization. While this isn't strictly following how Node behaves (you have to require a module once before its code runs), I think it's pretty important for striking a compromise for convenience in a browser environment.

I'm not sure how many modules use the array convenience for their main or bridge files, but I would guess the number is small. I did some analysis on all the Ender modules I could find in the wild back when I was contemplating some of these larger changes to the semantics, so maybe I should go back and update that to get a more precise count.

@ded
Copy link
Member

ded commented Aug 13, 2013

would be great to know! As long as none are mine 😉

@luk-
Copy link

luk- commented Aug 13, 2013

More control of the build is awesome, especially if it could make an easier road to getting source maps implemented.

@rvagg
Copy link
Member

rvagg commented Aug 13, 2013

Repeating my comment here for clarity: IMO: at this stage, since we mostly seem to be time-poor, he who does the work, gets to decide on what gets done, so over to you! Thanks for picking up some of the slack.

@amccollum if you have a vision for how this should work then I'm behind you going for it, my vision is limited at the moment because I'm stretched across too many things.

@ded
Copy link
Member

ded commented Aug 14, 2013

i tried reading thru each of the commits. does this finally give us support to include local files in packages....eg:

var parallel  = require('when/parallel')

parallel([a, b, c]).then(done)

@amccollum
Copy link
Contributor Author

Yeah, it does. It supports both relative includes within a package and cross-package submodule includes.

On Tue, Aug 13, 2013 at 7:53 PM, Dustin Diaz [email protected]
wrote:

i tried reading thru each of the commits. does this finally give us support to include local files in packages....eg:

var parallel  = require('when/parallel')
parallel([a, b, c]).then(done)

Reply to this email directly or view it on GitHub:
#181 (comment)

@ded
Copy link
Member

ded commented Aug 14, 2013

it would be great to have these branches published to npm as [email protected]so can immediately get a feel for them.

@amccollum
Copy link
Contributor Author

Ok, I think this branch is ready for others to try out. I had to remove some tests that were obsoleted by these changes, but there is currently only one test failing (a minifier test that seems unrelated, but I need to keep trying to track down the cause). I also added tests for the parts of ender-builder that were untested before.

A new regression in this build is the removal of the sans and noop arguments. These need to be rethought in a multiple base package world. In the case of sans, I think the solution is probably for you to be able to do something like --client-lib noop instead of --sans. The noop case is a little trickier since we're doing more than just concatenation now. My preference would probably be to just kill it, but there could be an alternate assembly mechanism that went back to the old behavior if it turns out this is a commonly-used option.

I've updated all the modified modules to have -dev versions, but I don't have permission to publish new versions of the modules to NPM.

@luk-
Copy link

luk- commented Aug 20, 2013

@rvagg can you npm owner add amccollum ender please?

@rvagg
Copy link
Member

rvagg commented Aug 21, 2013

done, and all the associated packages too, let me know if I've missed anything @amccollum, when you publish just remember to publish with --tag dev so they don't go under 'latest' and get auto-downloaded when people install (the actual versions are irrelevant) -- in case you didn't know.

@rvagg
Copy link
Member

rvagg commented Aug 21, 2013

oh, and I think you might have to pin exact versions across the packages otherwise npm will try and match 'latest' versions. So you can't use fuzzy matching like '~0.1.2-dev', you have to '0.1.2-dev', which gets really annoying when you want to update stuff.

@amccollum
Copy link
Contributor Author

Ok, I published this version under ender-2.0.0-dev. Let me know if you guys run to issues (which is definitely possible). There are a few aspects of the current code that could use some refactoring, so that's where my focus will be next.

@ded
Copy link
Member

ded commented Nov 7, 2013

@amccollum @rvagg k. i'll have a look now given that i was pretty excited about some of the new features you introduced...

@amccollum
Copy link
Contributor Author

I'm actually about to push some other improvements I've been working on that required a more major refactoring. For example, Bower support as the repository backend.

On Thu, Nov 7, 2013 at 1:52 PM, Dustin Diaz [email protected]
wrote:

@amccollum @rvagg k. i'll have a look now given that i was pretty excited about some of the new features you introduced...

Reply to this email directly or view it on GitHub:
#181 (comment)

@ded
Copy link
Member

ded commented Nov 7, 2013

@amccollum one thing i was looking for was require('when/parallel') but can't seem to get it to work

@amccollum
Copy link
Contributor Author

Yeah, so the one change that a module owner has to make to have this work as expected is to add a files key to their package.json, either at the top level, or under the ender subkey. The main and bridge files get included automatically, but you have to list everything else. We have to do this since we don't have access to the file system, and we have to know which files to include in the build. So, for example, adding this to the when package.json

  "ender": {
    "files": ["parallel.js"]
  },

lets you do require('when/parallel') (or require('./parallel') from inside the when package).

@ded
Copy link
Member

ded commented Nov 7, 2013

so unless i was missing something (obviously). i did a simple ender build when and then tried var parallel = require('when/parallel')....

edit: oh, just seeing your new comment now

@ded
Copy link
Member

ded commented Nov 11, 2013

ok, i went through and looked at all of it. i see you even kept support for index.js includes. i've been testing it with a few packages and haven't noticed any regressions.

i say we move forward with the big 2.0.0 release then i can help out with some updated learning material. also, it would be good to npm owner add each of the owners to the new packages....

@amccollum
Copy link
Contributor Author

I'd like to be given permissions to create new repos under the ender-js organization. As you saw, I created a new unified ender-package that handles all interfacing with packages on the CLI side, too. Generally, this simplifies the code (and reduces total code size by around 10%, mostly by getting rid of ender-dependency-graph), while also providing more correct package handling in a few cases. It also adds support for building anything NPM can install (git repos, tar balls, github shorthands like amccollum/sel, etc).

Not having package handling code sprinkled throughout different modules paves the way for adding support for Bower on the backend, which is what I'm currently working on. Not sure how excited people are about Bower as a backend, and if it is worth holding a 2.0.0 until it is done, but it should be pretty easy now.

Once I get the permissions for the organization, I'll push the full set of changes. I'd appreciate some help testing with the new handling of packages on the CLI side. I still need to add some tests for the new dependency mapping stuff, but otherwise the code and tests are in pretty good shape. I'll also add all the other owners to the new packages in npm.

@luk-
Copy link

luk- commented Nov 11, 2013

Is there any reason npm can't be used for the back end? Bower is just a front end for github, which npm handles.

@ded
Copy link
Member

ded commented Nov 11, 2013

yeah, the whole Bower thing... I just don't understand it. But anyway, yeah, I had a play with github urls too and that worked out nicely.

It looks like you also have a patch for the duplicate sub-include that i mentioned. It would be great to put that in as well.

Other than that, I'll set up each person with admin access.

... oh, and last but not least, it would probably be a good idea to re-think our licensing/contributor notes. I am more inclined to simply include a short URL linking to our copyright with also includes the proper list of contributors

@amccollum
Copy link
Contributor Author

I guess I don't really understand the appeal of Bower, either, but I imagine it will be attractive to some people to have that option. Obviously NPM should remain the unequivocal default.

@ded
Copy link
Member

ded commented Nov 13, 2013

@amccollum where we at with this? I can begin working on new docs

@amccollum
Copy link
Contributor Author

Sorry, got a little busy the last couple days. As soon as NPM comes back up, I should be able to run through all the tests one last time and then push/publish everything.

@ded
Copy link
Member

ded commented Nov 13, 2013

one other thing if you wouldn't mind. Add some examples of the new Module class in use outside of the building tool. Obviously it gets utilized, but perhaps show use cases where one would use it manually in a bridge or simple third party plugin outside of the ender compilation.

@amccollum
Copy link
Contributor Author

Ok, the new-packaging branches for all the ender-* package should be pushed, along with the new ender-package package. I also added all the other members as owners of the new packages (ender-package, ender-core, and ender-commonjs). The version in npm is [email protected], though npm has been acting really wonky for me today, so if you run into issues, let me know.

I'll start working on examples, and adding some final test coverage.

A few other things worth noting:

  • the --sans and --noop options are still AWOL, but I think I know how to bring them back (not sure if anyone would want to use them though now that the build uses the Module class)
  • ender is now a little bit more strict about resolving dependencies. Whereas previous versions would work if two packages each required a different version of the same dependency, the new version may fail with an error. In general, it's worth thinking about whether we care about fixing dependency conflicts like this.
  • Right now ender installs path packages even when they exist already in the node_modules directory (this was the previous behavior), but it would be pretty trivial to have it only install these packages if the version in node_modules is outdated. It seems like the use case of locally modifying packages (but not bumping the version every time) outweighs the slight slowdown of the unnecessary install, but maybe feel otherwise.
  • Other people will probably uncover things I'm missing here...

@ded
Copy link
Member

ded commented Nov 14, 2013

fwiw, i may have been the only one using --sans and --noop given that i'm a huge proponent of lazy loading and being able to bundle ender-js with a script loader, then loading other bundles with ender build ./core --sans

@ded
Copy link
Member

ded commented Nov 14, 2013

@amccollum i just checked npm owner ls ender-core — and it still just shows you as the owner. Can you add @rvagg (rvagg) and @luk- (luk), and myself

@ded
Copy link
Member

ded commented Nov 14, 2013

also closes #120

@amccollum
Copy link
Contributor Author

Yeah, nothing doing on adding you guys as owner, NPM just keeps erroring when I try... I'll create an issue there.

@luk-
Copy link

luk- commented Nov 14, 2013

@amccollum I work on npm, what's the command/output?

@amccollum
Copy link
Contributor Author

npm ERR! owner mutate Error getting user data for ender-core
npm ERR! Error: not_found missing: -/user/org.couchdb.user:ender-core
npm ERR!     at RegClient.<anonymous> (/usr/local/Cellar/node/0.10.21/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:272:14)
npm ERR!     at Request.self.callback (/usr/local/Cellar/node/0.10.21/lib/node_modules/npm/node_modules/request/request.js:129:22)
npm ERR!     at Request.EventEmitter.emit (events.js:98:17)
npm ERR!     at Request.<anonymous> (/usr/local/Cellar/node/0.10.21/lib/node_modules/npm/node_modules/request/request.js:873:14)
npm ERR!     at Request.EventEmitter.emit (events.js:117:20)
npm ERR!     at IncomingMessage.<anonymous> (/usr/local/Cellar/node/0.10.21/lib/node_modules/npm/node_modules/request/request.js:824:12)
npm ERR!     at IncomingMessage.EventEmitter.emit (events.js:117:20)
npm ERR!     at _stream_readable.js:920:16
npm ERR!     at process._tickCallback (node.js:415:13)

@luk-
Copy link

luk- commented Nov 14, 2013

@amccollum you might be using the wrong order of commands, are you doing npm owner add ded ender-core? You have to do the username first then the package name second.

@luk-
Copy link

luk- commented Nov 14, 2013

It's confusing.

@amccollum
Copy link
Contributor Author

@luk- That's embarrassing. It's been a long day. Thanks.

@luk-
Copy link

luk- commented Nov 14, 2013

It's cool, I work on npm full time and always have to check what it is, but I'm also kind of an idiot.

@amccollum
Copy link
Contributor Author

@luk- ok, well, I added you guys (again), but every so often I get this when I run the command:

npm ERR! owner mutate Error getting package data for ender-core
npm ERR! 404 'ender-core' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it
npm ERR! 404 
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, or http url, or git url.

npm ERR! System Darwin 13.0.1
npm ERR! command "/usr/local/Cellar/node/0.10.21/bin/node" "/usr/local/bin/npm" "owner" "add" "luk" "ender-core"
npm ERR! cwd /Users/andrew/Src/ender-js/ender-js
npm ERR! node -v v0.10.21
npm ERR! npm -v 1.3.11
npm ERR! code E404
npm ERR! 
npm ERR! Additional logging details can be found in:
npm ERR!     /Users/andrew/Src/ender-js/ender-js/npm-debug.log
npm ERR! not ok code 0

NPM has randomly been saying packages are either not in the registry, or versions are overwriting nonexistent version all day...

@luk-
Copy link

luk- commented Nov 14, 2013

@amccollum I'm getting the 404 on packages occasionally as well. This stuff should clear up in the next 24 hours, Unfortunately, I don't think there's really anything we can do about it in the meantime.

@luk-
Copy link

luk- commented Nov 14, 2013

If it doesn't work tomorrow I can get someone on the server side to take care of it for us.

@amccollum
Copy link
Contributor Author

It seems to be showing up correctly for now, so as long as it sticks, I think we're ok.

@ded
Copy link
Member

ded commented Nov 14, 2013

rock on

@ded
Copy link
Member

ded commented Nov 14, 2013

quick question. what is the new ender: { bare: true } option?

@amccollum
Copy link
Contributor Author

It indicates a core package that doesn't get wrapped in Module.loadPackage. You can look at the template in ender-builder to see how it gets woven in.

@ded
Copy link
Member

ded commented Nov 14, 2013

so basically ender-core and ender-commonjs are the only bare packages I take it

@amccollum
Copy link
Contributor Author

Right now, that's correct. Presumably if you were going to replace ender-core or ender-commonjs with a custom client/module lib, you would use it there, too. Or if you wanted to define a package that just didn't need the CommonJS mechanics at all.

@ded
Copy link
Member

ded commented Nov 16, 2013

@amccollum not sure what happened with the latest... but ender build . is dying on package.json files with github urls. it's definitely worth having a look :/

@ded
Copy link
Member

ded commented Nov 16, 2013

try throwing this in a folder

{
    "name": "example"
  , "version": "0.0.1"
  , "private": true
  , "dependencies": {
      "when": "cujojs/when"
  }
}

then ender build .

@amccollum
Copy link
Contributor Author

Yeah, looking at this now. There are two issues that make this fail right now. The first has to do with the way dependencies are converted into packages ids. Currently, the code just does id = name + '@' + value, but obviously that doesn't work in this case. The fix is to add a semver.valid check and then just use the value alone if it fails.

The second problem, though, is that the current dependency satisfaction code doesn't know how to figure out whether a dependency like this is met or not. To do that, it will need to record the actual name/version that is installed. This gets complicated since we install dependencies in batches. Let me play with this, though.

@ded
Copy link
Member

ded commented Nov 16, 2013

fwiw, it was working in the 2.0.0-dev version... it was just duplicating the main...

i've since tried adding logs and what not... and now they're stuck in npm and i don't remember publishing any of that today... and it's driving me mad

@amccollum
Copy link
Contributor Author

Ah, so 2.0.0-dev just used the keys of the dependencies array (it ignored versions). So it would have "worked", but it would have installed when from npm instead of from the git repo. The previous versions of ender never cared about package versions at all.

@ded
Copy link
Member

ded commented Nov 16, 2013

i think an appropriate GH url is foo/bar#<SHA | TAG | BRANCH> // @luk-

@amccollum
Copy link
Contributor Author

I think the solution here is going to be to keep track of a mapping from installed ids to packages on disk, so when we look for something that has been installed, we know how to find it.

@ded
Copy link
Member

ded commented Nov 16, 2013

anyway, i can't seem to use 2.0.1-dev without my bogus console.logs showing up and i am positive i never published them. it's from this bogus commit, which is now in npm for whatever reason ender-js/ender-package@3deecaa#diff-6d186b954a58d5bb740f73d84fe39073L129

@amccollum
Copy link
Contributor Author

Ok, I pushed a set of changes to ender-repository, ender-package, and ender-install that should allow the use of github, path, etc., urls as dependencies:

ender-js/ender-repository@2e60c5d
ender-js/ender-package@af9f66b
ender-js/ender-installer@f33686c

@ded
Copy link
Member

ded commented Nov 16, 2013

i got this working now. given i've been using when as a usecase, i went ahead and did ender build cujojs/when on both package.json and the CLI version. both worked.... except now i'm baffled why my simple demo code doesn't work

<script src='ender.js'></script>
<script src='example.js'></script>
var when = require('when')

var a = function a() {
  console.log('a')
  return when.resolve('hello')
}

var b = function b() {
  console.log('two')
  return when.promise(function (res) {
    setTimeout(function() {
      res('world')
    }, 100)
  })
}

var c = function c() {
  console.log('three')
  return 'almost'
}

var parallel = require('when/parallel')
parallel([a, b, c]).then(function (a) {
  console.log(a)
})

I get no logs in the browser, but when run in node... node example.js — all the logs come through. Perhaps there something spooky I don't know...

cc // @cujojs

@ded
Copy link
Member

ded commented Nov 16, 2013

alright... i'm actually going crazy and probably missing how JavaScript is working. I know this is besides this issue, but I may as well ask how the hell this works...

function parallel(tasks /*, args... */) {
  return when.all(Array.prototype.slice.call(arguments, 1)).then(function(args) {
    return when.map(tasks, function(task) {
      return task.apply(null, args);
    });
  });
};

wouldn't slice.call(arguments, 1) return all other arguments except the first? i log it each time and it's empty 🐙

@ded
Copy link
Member

ded commented Nov 16, 2013

@rvagg @luk- i missed the --tag dev bit. is it still needed even when your semver is suffixed with -dev?

@amccollum
Copy link
Contributor Author

Yeah, oddly, it is.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants