Three dependency changes in my site ended with three different outcomes. Sharp came out of package.json but stayed in the dependency tree. The yaml package disappeared from both. The AWS SDK stayed because its proposed replacement didn’t cover the behavior the application needed.
Calling all of that “removing dependencies” leaves out the useful part.
Sharp stopped being a direct dependency
The media pipeline used Sharp to generate image sizes and WebP variants. Switching that work to Bun.Image removed the application’s direct use of Sharp.
It did not remove Sharp from the installation. Astro still requested it as an optional dependency for its image service. With the application’s version requirement gone, the lockfile resolved Astro’s version instead. In that change, removing a dependency also meant selecting an older version of it.
The code change still had value. The media pipeline used the runtime’s image API, and there was one less direct dependency to maintain. But it wasn’t a smaller dependency tree in the way the manifest diff suggested.
There were benchmarks attached to the change, too. They compared Sharp under Node with Bun.Image under Bun, so they measured two runtime setups, not just two image libraries. Useful context for that application, but not a general performance verdict or evidence that Sharp had left the installation.
YAML did leave
The sync script used the yaml package to parse and serialize frontmatter. Those were the operations replaced with Bun.YAML.
Once that direct dependency was removed, nothing else in the resolved tree required it. The package disappeared from the lockfile as well.
The YAML change completed the removal: the calls were replaced, the declaration was deleted, and the resolver no longer needed the package. It doesn’t need a benchmark to be worthwhile.
The AWS SDK evaluation ended differently. The proposed replacement didn’t preserve the upload behavior the application depended on, so the SDK stayed. Fewer packages would have been nice, but that wasn’t enough reason to change the behavior.
Installation permissions are a separate question
The Sharp change also removed an entry from trustedDependencies. That’s worth reviewing, but it’s another kind of change.
Bun’s lifecycle-script policy controls which dependency install scripts it will run. It is not a sandbox around installed packages, and deleting one trust entry is not proof that a package can never execute code. The effective policy also depends on Bun’s defaults and the rest of the project configuration.
I want a dependency review to distinguish those outcomes:
- Does the application still import the package?
- Does another dependency still bring it into the installation?
- What install-script permissions does the effective configuration allow?
Those questions can have different answers for the same package.
The manifest was correct: Sharp was no longer a direct dependency. The lockfile was also correct: Astro still needed it. The mistake would have been treating the first diff as proof of the second.
After deleting a dependency declaration, I want to see what the resolver kept.
Sources
- Bun.Image documentation — the runtime image API used in the replacement.
- Bun.YAML documentation — parsing and serialization support.
- Astro images guide — Astro’s built-in image services.
- Bun lifecycle scripts — dependency trust and install-script behavior.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].