-
Notifications
You must be signed in to change notification settings - Fork 239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RRFC] Add libc fields to select optionalDependencies should be installed or skipped #438
Comments
Also as {
"name": "example",
"version": "0.0.1",
"optionalDependencies": {
// for node-v8.x
"example-linux-x64-v57-gnu": "0.0.1",
// for node-v10.x
"example-linux-x64-v64-gnu": "0.0.1",
// for node-v12.x
"example-linux-x64-v72-gnu": "0.0.1",
// for node-v14.x
"example-linux-x64-v83-gnu": "0.0.1",
// for node-v16.x
"example-linux-x64-v93-gnu": "0.0.1",
} |
If node.js put more of that info in The other workaround is to use a For selecting based on node version, you can use (For non-optional deps, a failing install script will fail and roll back the entire install, and in the case of a mismatched |
It won't be a suitable solution if #488 landed |
@styfle here is |
@Brooooooklyn Yeah that sounds like it could work 👍 I could imagine a new package.json field with However, I'm not sure how this would work for the musl version. How would you negate it? I'm almost thinking we need to expose |
In my opinion, And I don't like the idea that introduce |
I like the Now the question is, does it make sense to implement this in Node.js core or should this be implemented in npm? The advantage of Node.js core is that other package managers could easily implement the feature (yarn, pnpm, etc). The disadvantage of Node.js core is that the user must update both node and npm in order to use this feature. |
Hello, I help maintain the There's a list of possible improvements in lovell/detect-libc#14 that might be of interest. |
While a little off-topic, I'm open to add support for a Main issue I'd have is the difficulty around detecting it ( |
/cc @zkochan |
Node.js already has the {
"header": {
"reportVersion": 1,
"nodejsVersion": "v12.0.0-pre",
"glibcVersionRuntime": "2.17",
"glibcVersionCompiler": "2.17",
"wordSize": "64 bit",
"arch": "x64",
"platform": "linux",
"componentVersions": {
"node": "12.0.0-pre",
"v8": "7.1.302.28-node.5",
"uv": "1.24.1",
"zlib": "1.2.11",
"ares": "1.15.0",
"modules": "68",
"nghttp2": "1.34.0",
"napi": "3",
"llhttp": "1.0.1",
"openssl": "1.1.0j"
}
}
} But only for The |
Right, the implementation of the skip mechanism will be up to each package manager, I'm not too worried about that. My point is that knowing whether the system uses the glibc or musl should ideally come from either |
cc @Jarred-Sumner, I know he did some optimizations around optional dependencies in Bun |
Bun skips postinstall while retaining compatibility with native dependencies that have binary executables by allowlisting some packages to have the first dependency matching os/cpu constraints to become the source where Giving some packages special treatment is not great, but there currently is no way to specify this behavior in package.json or in the registry API response. This approach also only works with native executables, not native bindings Instead of that, here is what I would propose
{
"name": "@napi-rs/canvas",
"version": "0.1.6",
"nativeDependencies": {
"linux-x64-gnu": {
"@napi-rs/canvas-linux-x64-gnu": "0.1.6"
},
"linux-x64-musl": {
"@napi-rs/canvas-linux-x64-musl": "0.1.6"
},
"darwin-x64" : {
"@napi-rs/canvas-darwin-x64": "0.1.6"
},
"win32-x64" : {
"@napi-rs/canvas-win32-x64": "0.1.6"
},
"linux-aarch64-gnu": {
"@napi-rs/canvas-linux-aarch64-gnu": "0.1.6"
},
"linux-aarch64-musl": {
"@napi-rs/canvas-linux-aarch64-musl": "0.1.6"
}
}
} This would tell package managers they need to install the most specific matching package. On Ubuntu 18.04 AMD64, a package manager would try:
Ideally, these dependencies would not be allowed to have their own dependencies. That would enable package managers to improve installation times by skipping extra registry API metadata requests when the exact version of the native dependency is specified. This means adding additional native targets won't impact package installation time. |
I like this idea.
And this. I think we can design a different installation logic for native packages than for normal npm packages, considering that native packages are platform-related. The best solution I can imagine is:
I think this RRFC should be turned into add What do you think? |
There's already an open RFC discussing this feature, here: It's still waiting for npm to join the discussion there, and I'm not interested to contribute to another RFC around this topic until they do. The |
What if none of these match the current platform? Can it fallback to a wasm variant and how would you define that?
I'm happy with that for now! Its the least amount of changes to solve the original issue 👍 |
Yes, it would be |
We can define platform triple like |
Relates to: #519 |
Action item from our OpenRFC call: Let's follow up with the idea laid out in this RRFC and work on a sep RFC that can encompass more things that can possibly affect whether an optional dependency gets installed or not. This new RFC can complement the work from #519 and provide a better package distributions experience. |
@styfle lets do it. We can chat about this tomorrow (ie. in the next RFC call) but I think this is something we can agree on given the previous implementations. |
Sounds good! I watched the recording and seems like there was no opposition 👍 |
@darcyclarke Is anyone implementing this feature? Whats the roadmap look like? |
Update, seems to be not working. |
Has anyone confirmed that this feature is working as intended for people using the latest A popular package that has taken advantage of the new However the latest version of musl$ docker run -it --rm node:20-alpine /bin/sh
# npm install -g npm@latest
# npm -v
10.2.0
# npm install @swc/core
added 5 packages in 11s
# npm ls --depth 1
`-- @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- @swc/[email protected]
+-- @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/helpers@^0.5.0
`-- @swc/[email protected]
# ls -al node_modules/@swc/
total 28
drwxr-xr-x 7 root root 4096 Oct 9 19:53 .
drwxr-xr-x 3 root root 4096 Oct 9 19:53 ..
drwxr-xr-x 3 root root 4096 Oct 9 19:52 core
drwxr-xr-x 2 root root 4096 Oct 9 19:52 core-linux-x64-gnu
drwxr-xr-x 2 root root 4096 Oct 9 19:52 core-linux-x64-musl
drwxr-xr-x 2 root root 4096 Oct 9 19:52 counter
drwxr-xr-x 2 root root 4096 Oct 9 19:52 types glibc$ docker run -it --rm node:20-bullseye /bin/sh
# npm install -g npm@latest
# npm -v
10.2.0
# npm install @swc/core
added 5 packages in 9s
# npm ls --depth 1
`-- @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- @swc/[email protected]
+-- @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/[email protected]
+-- @swc/[email protected]
+-- UNMET OPTIONAL DEPENDENCY @swc/helpers@^0.5.0
`-- @swc/[email protected]
# ls -al node_modules/@swc/
total 28
drwxr-xr-x 7 root root 4096 Oct 9 20:09 .
drwxr-xr-x 3 root root 4096 Oct 9 20:09 ..
drwxr-xr-x 3 root root 4096 Oct 9 20:09 core
drwxr-xr-x 2 root root 4096 Oct 9 20:09 core-linux-x64-gnu
drwxr-xr-x 2 root root 4096 Oct 9 20:09 core-linux-x64-musl
drwxr-xr-x 2 root root 4096 Oct 9 20:09 counter
drwxr-xr-x 2 root root 4096 Oct 9 20:09 types I really want to take advantage of this feature so hopefully this is a case of me missing something obvious. |
libc is not overridable yet, only cpu and os. This PR is where the libc override is happening. The underlying dependency supports it and landed in |
@wraithgar I think we should reopen this issue. The original post says that the libc field should be used to avoid postinstall by only installing the correct optionalDendencies. I just tried the latest npm and latest sharp and it is still installing both musl and gnu binaries but alpine should only install musl binaries. DockerfileFROM node:20-alpine3.18
RUN mkdir /app
WORKDIR /app
RUN npm i -g [email protected]
RUN npm add [email protected]
RUN ls -lA node_modules/@img build command
output
|
|
I confirmed that it is fixed in |
Bumps to [`[email protected]`](https://github.com/npm/cli/releases/tag/v10.4.0) which adds a fix for [arborist](npm/cli#7126) which will avoid installing multiple libc binaries and [correctly select glibc vs musl](npm/rfcs#438) from the optionalDependencies.
Motivation ("The Why")
Example
For my packages published as prebuilt native addons, I config the native packages cross-platform as
optionalDependencies
to let npm choose the suitable one to download. And I can avoid writtenpostinstall
scripts to download them in this way.Like canvas package:
The
@napi-rs/canvas
package is published for users depending on it directly:And the packages include prebuilt native addons:
In the macOS/Windows/FreeBSD this mechanism works fine, but on the Linux systems, npm will download two native binding packages, both
gnu
andmusl
. It will significantly increase the install size. The install size of@napi-rs/canvas
on linux-x64 systems is 37mb which could be the half of it.References
The text was updated successfully, but these errors were encountered: