npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@entwico/nft-docker

v1.0.1

Published

NFT-based Docker optimization for Node.js apps

Readme

@entwico/nft-docker

A CLI tool for optimizing Node.js Docker images using @vercel/nft (Node File Trace). It traces your application's entrypoint(s) to determine exactly which files under node_modules/ are actually needed at runtime, then deletes everything else — resulting in significantly smaller Docker images.

Intended to be used via npx inside Dockerfiles — it is NOT a project dependency.

Why

  • Many frameworks (e.g. Astro) list build-time dependencies (Vite, esbuild, etc.) alongside runtime dependencies. pnpm deploy --prod or npm prune --production cannot distinguish build-only imports from runtime imports. NFT traces actual runtime file usage, producing much smaller output.
  • pnpm compatibility: pnpm's default symlinked node_modules layout breaks naive file-copy pruning. This tool handles the workaround automatically.

CLI commands

npx @entwico/nft-docker install -e <entrypoint> [...]

All-in-one command for Docker builds. Runs the full cycle: preinstall, dependency installation, and pruning.

  1. Patches .npmrc with node-linker=hoisted if the project uses pnpm.
  2. Runs the appropriate frozen install command (pnpm install --frozen-lockfile / npm ci / yarn install --frozen-lockfile).
  3. Traces the given entrypoint(s) with @vercel/nft and removes all non-traced files from node_modules/.

npx @entwico/nft-docker preinstall

Prepares the environment for a compatible node_modules layout before installing dependencies.

  • Detects the package manager from packageManager field in package.json, falling back to lockfile detection.
  • If pnpm: ensures .npmrc has node-linker=hoisted (creates or appends as needed).
  • If npm or yarn: no-op.

npx @entwico/nft-docker prune -e <entrypoint> [...]

Traces entrypoint(s) and removes all non-traced files from node_modules/.

  • Runs nodeFileTrace() on the given entrypoint(s).
  • Deletes every file in node_modules/ that is NOT in the traced set (single pass, in place).
  • Removes empty directories left behind.

Dockerfile usage

Simple: build in CI, prune in Docker

If your app is already built before the Docker build (e.g. in a CI step), you only need to prune:

FROM node:24-alpine

# enable corepack for pnpm (skip if using npm)
RUN corepack enable pnpm

WORKDIR /srv

RUN addgroup -S app && adduser -S app -G app && apk add --no-cache tini

COPY package.json pnpm-lock.yaml /srv/
COPY dist/ /srv/dist/

RUN npx @entwico/nft-docker install -e ./dist/server/entry.mjs

USER app
ENTRYPOINT ["tini", "--", "node", "./dist/server/entry.mjs"]

Full: install, build, and prune inside Docker

When the Docker build handles everything, use the individual commands so the build step runs between install and prune:

FROM node:24-alpine AS builder

# enable corepack for pnpm (skip if using npm)
RUN corepack enable pnpm

WORKDIR /srv

# install dependencies with hoisted node_modules
COPY package.json pnpm-lock.yaml /srv/
RUN npx @entwico/nft-docker preinstall
RUN pnpm install --frozen-lockfile

# build
COPY . /srv/
RUN pnpm run build

# prune node_modules to runtime-only files
RUN npx @entwico/nft-docker prune -e ./dist/server/entry.mjs

# --- final image ---
FROM node:24-alpine

WORKDIR /srv

RUN addgroup -S app && adduser -S app -G app && apk add --no-cache tini

COPY --from=builder --chown=app:app /srv/node_modules /srv/node_modules/
COPY --from=builder --chown=app:app /srv/dist /srv/dist/

USER app
ENTRYPOINT ["tini", "--", "node", "./dist/server/entry.mjs"]

For npm-based projects, replace the lockfile and drop the corepack line — everything else stays the same.

Multiple entrypoints

If your app has multiple entrypoints (e.g., a server and a worker), pass them all:

npx @entwico/nft-docker install -e ./dist/server/entry.mjs -e ./dist/worker/index.mjs

NFT merges the trace results, keeping files needed by any entrypoint.

License

MIT