-
Notifications
You must be signed in to change notification settings - Fork 12
Versioned core modules #9
Comments
This isn't entirely accurate. There are some technical limitations we should acknowledge. I don't think it's practical to ship with every version of every stdlib module, especially if we want to continue bundling them in the way we do now. If we decide to ship with a single version then we also need to acknowledge that many core modules depend on each other. |
Ahh, that makes much more sense, now I understand.
Yeah, that's the tricky part. The |
Treating core modules like npm modules feels like an overapplication of an abstraction that works in one case to another case where it fits uncomfortably (sort of a "when you have a hammer, screws are just difficult nails" situation.) Core modules are the only modules in io.js that can declare a global abstraction that is invariant across packages. That means that those abstractions are safe to return or accept across package boundaries. For example, http requests, event emitters, streams, crypto hashes, etc, are all okay to accept or return from your module. Userland is not able to make these guarantees – the classic example is voxel.js's issues with vectors, which was solved by downcasting parameters and returns to a shared type (array) between packages, before upcasting back to "ndarray" internally. It's also seen in http middleware – adding attributes to an existing type creates a new type, of sorts, which at best, silos a package's use to a given framework ecosystem, and at worst, ends up in peerDependency hell. Allowing userland to "pick" core library versions means giving up the ability to make global, cross-package abstractions in core. That means that global, cross-package abstractions will be difficult to enforce anywhere in the ecosystem, even when they start to become necessary. I worry that versioning "core" runs into the same problem, also – when you |
minor point but the import express from "@strongloop/express@2" |
Being able to specify aliases/mappings up in the {
"aliases": {
"url": "url@2",
"express": "@strongloop/express@2"
}
} Another alternative could be to attach versions to the core namespace: import { http } from "core" // current version
import { fs } from "core@3" // previous
import { url } from "core@2" // legacy io.js |
+1 on @timoxley suggestion. I like the |
One negative outcome from dependency defined as |
Other thing is bothering me, even if you can control your own code, you can't do the same for 3rd party node modules. For example i used some In this case consumers can benefit a lot from In case if app can be run in different nodejs versions then aliases idea can be extended with aliases binded to nodejs versions. {
"aliases": {
"v5": { "url": "url@2" },
"v6": { "url": "url" }
}
} |
This isn't an issue because |
it will become a problem for npm ecosystem when evolved |
Part of the point of the NG brainstorming is to see how we can make backward-incompatible changes to core.
One early proposal was to use ES6 modules as a "switch":
const fs = require("fs")
gives you the existing fs, andimport fs from "fs"
gives you "fs v2" with back-compat breakages. However, this suffers from the "this time we'll do it right!" fallacy, and assumes we won't ever want to break back-compat again. (Or at least, it doesn't have a strategy for doing so.)I think a better approach would be to start versioning the core modules. The version numbers that are used in code would be a single number, i.e. 1 or 2, not 1.3.4; we only need to signal back-compat breakages, not additions or fixes. There are a variety of ways you could envision this working then:
require
andimport
do the exact same thing, and"fs"
is an alias for"fs@1"
require
stays unchanged and can only ever require"fs"
;import
cannot import"fs"
, but can import"fs@1"
or"fs@2"
or...(I think I like the second better; however, it does mean we block progress on this idea until ES6 modules ships in V8, and that could be a long time.)
Relatedly there comes the question of how we distribute these modules. Here is one scheme that I like:
"fs@1"
in addition to the normal way.The text was updated successfully, but these errors were encountered: