Skip to content

fix: support the packaging format of sharp v0.34.x - #199

Merged
styfle merged 7 commits into
vercel:mainfrom
yjoer:patch-3
Jul 10, 2025
Merged

fix: support the packaging format of sharp v0.34.x#199
styfle merged 7 commits into
vercel:mainfrom
yjoer:patch-3

Conversation

@yjoer

@yjoer yjoer commented Jul 4, 2025

Copy link
Copy Markdown
Contributor

The idea is stolen from nft, where we introspect package.json to retrieve optional dependencies containing the native addon and relocate them. Following that, I patched the third item within the path list, which will be used to load the addon file in the subsequent lines.

Since the prebuilt binaries are available on all platforms I could name, we may ignore the WASM builds. I've added integration tests requiring actual packages, but haven't updated the CI workflow yet, as it would cause longer CI times. The tests include sharp v0.34.2 and v0.32.6 to ensure the new mechanism doesn't affect the existing workflow. I've also run the scripts on both Windows and Linux (x64), and they worked as expected.

Another caveat is on the loading of libvips. On Windows, the dynamic libraries are included in a single package. While for Linux and Mac, they are divided into two packages. From a quick search, it seemed that they are only needed to build the binding. Currently, they are copied, but nothing in the source is changed to load them.

// windows
sharp
└─ @img/sharp-win32-x64

// linux
├─ @img/sharp-libvips-linux-x64
├─ @img/sharp-libvips-linuxmusl-x64
├─ @img/sharp-linux-x64
└─ @img/sharp-linuxmusl-x64

// mac
├─ @img/sharp-darwin-arm64
└─ @img/sharp-libvips-darwin-arm64

Fixes: vercel/ncc#1153

@yjoer
yjoer requested review from Timer and styfle as code owners July 4, 2025 18:33
@socket-security

socket-security Bot commented Jul 4, 2025

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedsharp@​0.32.6981001008970
Addedsharp@​0.34.29210010089100

View full report

@yjoer

yjoer commented Jul 4, 2025

Copy link
Copy Markdown
Contributor Author

On libvips, I tried deleting the sharp-libvips-linux-x64 folder, and the terminal screams at me.

ERR_DLOPEN_FAILED: libvips-cpp.so.8.16.1: cannot open shared object file: No such file or directory

It is good when the folders are colocated, which is already the case.

assets
├─ @img/sharp-libvips-linux-x64
└─ @img/sharp-linux-x64

@yjoer

yjoer commented Jul 8, 2025

Copy link
Copy Markdown
Contributor Author

Should I include the packages used in the integration test in dev dependencies instead? 🤔

@styfle

styfle commented Jul 9, 2025

Copy link
Copy Markdown
Member

Yeah I think we generally add the deps for tests into devDependencies

@styfle

styfle commented Jul 9, 2025

Copy link
Copy Markdown
Member

If we don't have any existing tests like this, you could update the CI command to install the subdirectory too

@yjoer

yjoer commented Jul 9, 2025

Copy link
Copy Markdown
Contributor Author

This is ready for review. All nested optional dependencies are already included within the optional dependencies of the main package. Relocating them separately isn't necessary. Leaving the implementation here in case I've missed any packages.

try {
  for (const innerDep of Object.keys(pkg.optionalDependencies || {})) {
    const innerDir = path.resolve(fs.realpathSync(dir), '..', '..', innerDep);
    emitAssetDirectory(innerDir);
  }
} catch (err) {
  if (err && err.code !== 'ENOENT') {
    console.error(`Error reading 'sharp' dependencies from '${dir}/package.json'`);
    throw err;
  }
}


const fs = require('fs');

expect([26, 27]).toContain(output.length);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason this assertion for output length was removed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the way webpack is invoked in d7ee3a0 so that the executions within the compilation are propagated to the coverage report. The output string from the standard output is replaced with a stats object. I am not aware of a way to retrieve a string like previous stdout from that object, so I replaced the assertion by checking the number of errors. The object provides a list of assets emitted, too, but the number of assets varies between platforms, making it suboptimal for assertion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case the compilation fails, the promise is thrown, and the test fails. There isn't a try-catch block attempting to recover from or hide failures.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right. I can assert the number of chunks, since it remains stable unless the entry point changes or dynamic imports are added. Matching the list of emitted assets with regexes for a set of expected files works as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 0093631

@styfle styfle changed the title feat: support the packaging format of sharp v0.34.x fix: support the packaging format of sharp v0.34.x Jul 10, 2025
@styfle
styfle merged commit 2efe28c into vercel:main Jul 10, 2025
7 checks passed
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.9.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: Fails to bundle sharp@0.33.1

2 participants