惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
K
Kaspersky official blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
C
Cybersecurity and Infrastructure Security Agency CISA
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News - Newest:
Hacker News - Newest: "LLM"
Cisco Talos Blog
Cisco Talos Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Cyberwarzone
Cyberwarzone
L
LINUX DO - 最新话题
PCI Perspectives
PCI Perspectives
酷 壳 – CoolShell
酷 壳 – CoolShell
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
N
News and Events Feed by Topic
V
Vulnerabilities – Threatpost
T
Troy Hunt's Blog
GbyAI
GbyAI
C
CERT Recently Published Vulnerability Notes
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
量子位
Scott Helme
Scott Helme
月光博客
月光博客
Attack and Defense Labs
Attack and Defense Labs
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
Project Zero
Project Zero
G
GRAHAM CLULEY
博客园 - 【当耐特】
Recorded Future
Recorded Future
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
小众软件
小众软件
D
DataBreaches.Net
T
The Blog of Author Tim Ferriss
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
O
OpenAI News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
S
Security @ Cisco Blogs
The Last Watchdog
The Last Watchdog
MongoDB | Blog
MongoDB | Blog
H
Hacker News: Front Page
Latest news
Latest news
P
Proofpoint News Feed

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
pnpm vs npm vs yarn in 2026: I ran all three on my real monorepo and it forced me to change my mind
Juan Torchia · 2026-05-10 · via DEV Community

pnpm vs npm vs yarn in 2026: I ran all three on my real monorepo and it forced me to change my mind

The correct answer for speeding up installs in a monorepo is to make hoisting stricter. I know that sounds backwards. More strictness should mean more compatibility errors, more debugging time, more friction. And yet that's exactly what pushed me to adopt pnpm — after it first broke a Radix UI dependency at the worst possible moment.

That's the honest trade-off no synthetic benchmark shows you: pnpm is faster and leaner, but its strict hoisting model has teeth. When it bites, it hurts. And the official migration guide doesn't warn you when it's about to bite.

A few months ago I was deep in a sprint — Next.js 16 monorepo, strict TypeScript, Shadcn/ui, Radix UI, everything running on Railway. I switched from npm to pnpm following the usual benchmarks — you know the ones, they measure a react install with three dependencies on a clean machine. In production, the result was different.

My thesis: pnpm wins the overall comparison in 2026, but the compatibility cost is real and measurable. Yarn Berry is the hardest to justify today. And npm improved so much in v10 that it's no longer the obvious thing to throw out.


pnpm vs npm 2026 in a monorepo: the numbers that actually matter

I ran all three on the same project — a monorepo with two Next.js 16 apps and a shared TypeScript utilities package. Same machine, same clean lockfile, same connection. CI numbers came from Railway with cache disabled to measure the real cold install.

Install time (cold cache, Railway CI)

Package Manager Install time Disk usage (node_modules)
npm 10.9 87s 1.4 GB
yarn berry 4.5 72s 890 MB (PnP mode)
pnpm 9.15 41s 610 MB

pnpm is ~53% faster than npm on a cold install and uses less than half the disk. Yarn Berry with PnP is interesting on disk, but the install time doesn't justify PnP's compatibility cost — which is even more aggressive than pnpm's.

With CI cache warm (the everyday scenario), the gap compresses but doesn't disappear:

# Warm cache — same project, three runs averaged
# npm: ~18s | yarn berry: ~14s | pnpm: ~9s

Enter fullscreen mode Exit fullscreen mode

The case that changed my mind: Radix UI and strict hoisting

This is what benchmarks don't measure. pnpm by default doesn't do flat hoisting like npm. Each package can only import what's declared in its own package.json. In theory, that's correct. In practice, there are dependencies that rely on npm's ghost hoisting — they access packages they never explicitly declared.

It happened to me with a specific version of @radix-ui/react-dialog that internally depended on @radix-ui/react-compose-refs without properly declaring it in its own package.json. npm resolved it silently through flat hoisting. pnpm blew up with a cryptic error:

# Error that showed up in the Next.js 16 build
# Cannot find module '@radix-ui/react-compose-refs'
# Require stack:
#   - node_modules/.pnpm/@radix-ui+react-dialog@1.0.5/node_modules/@radix-ui/react-dialog/dist/index.js

# This is not your bug — it's the dependency failing to declare its own dep

Enter fullscreen mode Exit fullscreen mode

The fix that worked while I waited for the upstream patch:

# .npmrc at the monorepo root
# Enable public hoisting for Radix packages that have this problem
public-hoist-pattern[]=@radix-ui/*
public-hoist-pattern[]=@floating-ui/*

Enter fullscreen mode Exit fullscreen mode

This .npmrc tweak tells pnpm to do public hoisting for those specific scopes, replicating npm's behavior only where it hurts. Not elegant. Pragmatic.


Real pnpm monorepo configuration

If you're going to run pnpm in a Next.js 16 monorepo, this is the configuration that survived production. Not the 10-minute tutorial config — the one that emerged after two weeks of debugging:

# pnpm-workspace.yaml
packages:
  - 'apps/*'
  - 'packages/*'
  # exclude e2e folders so they don't step on monorepo deps
  - '!**/e2e/**'

Enter fullscreen mode Exit fullscreen mode

# .npmrc — monorepo root
# Public hoisting for packages that treat npm's flat hoisting as a feature
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=@radix-ui/*
public-hoist-pattern[]=@floating-ui/*

# Strict mode for everything else — pnpm's default
node-linker=node-modules

# Shamefully hoist: NEVER enable this in production
# shamefully-hoist=true  ← this is giving up; it turns pnpm into expensive npm

Enter fullscreen mode Exit fullscreen mode

The shamefully-hoist=true you see in some tutorials is total surrender. If you enable it, you're running pnpm with npm's behavior — you pay the cost of learning pnpm without taking any of the strictness benefits with you.

Workspace protocol and internal dependencies

// packages/ui/package.json  shared package
{
  "name": "@my-monorepo/ui",
  "version": "0.0.1",
  "dependencies": {
    // workspace:* tells pnpm to resolve from the local workspace
    // never from npm registry  this is critical for development
    "@my-monorepo/utils": "workspace:*"
  }
}

Enter fullscreen mode Exit fullscreen mode

// apps/web/package.json
{
  "dependencies": {
    "@my-monorepo/ui": "workspace:*",
    // exact Next.js 16 version  no ranges in production
    "next": "16.0.2"
  }
}

Enter fullscreen mode Exit fullscreen mode


The gotchas no synthetic benchmark measures

1. Lifecycle scripts and pnpm's PATH

pnpm doesn't add dependency binaries to your PATH the same way npm does. If you have scripts that call next or tsc directly in the shell (not via package.json scripts), they'll fail:

# This fails with pnpm if next isn't in your global PATH
$ next build

# This always works — pnpm resolves the workspace binary
$ pnpm next build
# or via package.json script:
# "build": "next build"

Enter fullscreen mode Exit fullscreen mode

2. pnpm dlx vs npx — they're not the same thing

# npx installs and caches globally by default
npx create-next-app@latest my-app

# pnpm dlx installs to a temp directory, no caching
# cleaner, slower on repeat runs
pnpm dlx create-next-app@latest my-app

# For tools you use frequently, install globally:
pnpm add -g @railway/cli

Enter fullscreen mode Exit fullscreen mode

3. Strict TypeScript and implicit re-exports

With strict TypeScript and pnpm, implicit re-exports from poorly-typed packages break earlier — which is actually an advantage disguised as a problem. pnpm forces you to discover implicit dependencies that npm would have never surfaced. That happened to me with a utilities library that was re-exporting lodash types without having it in its own dependencies.

This connects to something I already covered in the post about supply chain attacks in npm vs PyPI: the implicit dependency graph is exactly where the most interesting attack vectors live. pnpm makes that graph explicit. That's uncomfortable at first and valuable afterwards.

4. Railway CI and the pnpm store cache

Railway doesn't cache node_modules by default. With npm that stings a little. With pnpm it stings less because pnpm's store lives separately from the project:

# In your Dockerfile or Railway config
# Cache the pnpm store, not node_modules
ENV PNPM_HOME="/root/.local/share/pnpm"
ENV PATH="$PNPM_HOME:$PATH"

# The store lives outside the project — cacheable across builds
RUN pnpm config set store-dir /root/.pnpm-store

Enter fullscreen mode Exit fullscreen mode

If you don't set this up, every Railway build does a cold install even when the lockfile didn't change. The separate pnpm store is the feature that impacts CI the most — more than the raw install time itself.

5. Yarn Berry in 2026: who is it even for?

Being honest: I couldn't find a use case in my stack where Yarn Berry was the right answer. PnP breaks more things than pnpm's strict hoisting, the documentation assumes you know exactly what you're doing, and the install time advantage over pnpm isn't enough to justify the friction.

Yarn Berry makes sense if you're coming from a massive monorepo already configured with PnP and you don't want to migrate. If you're starting from scratch today, pnpm is the more direct answer. This isn't tribalism — it's that I couldn't find a single benchmark of my own where Yarn Berry won on something I actually cared about.


Compatibility table with the real stack

Dependency npm 10 yarn berry 4 pnpm 9
Next.js 16 ✅ (with sdk)
Shadcn/ui ⚠️ (PnP quirks) ✅ (with public-hoist)
Radix UI ⚠️ ⚠️ (versions < 1.1.x)
TypeScript 5.7
ESLint 9 ⚠️ ✅ (with public-hoist)
Prisma 6 ⚠️ (postinstall)

⚠️ = works but requires extra configuration not documented in the official README


FAQ: pnpm vs npm 2026 monorepo

Is it worth migrating from npm to pnpm on an existing project?

If the project is already in production and stable, evaluate it by CI cost. If your Railway pipeline (or any CI) runs installs frequently, the ~50% cold install difference adds up to real build hours per month. If the pipeline is short or already has aggressive caching, the urgency drops. The migration itself takes half a day plus two days of debugging edge cases — like the Radix UI one I described above.

What is pnpm's strict hoisting and why does it matter?

In npm, all packages are installed into a flat node_modules. Any package can access any other package, even if it didn't declare it as a dependency. pnpm instead creates a node_modules with symlinks where each package only sees what it declared. This prevents phantom dependencies but breaks packages that rely on npm's flat behavior. The official pnpm documentation explains the model in detail.

Does shamefully-hoist=true solve the compatibility problems?

Technically yes, but it's a partial surrender. If you enable shamefully-hoist=true, pnpm behaves like npm in terms of hoisting — you lose exactly the strictness benefit that makes pnpm valuable. The right alternative is public-hoist-pattern for the specific scopes that have the problem, not enabling global hoisting.

Is Yarn Berry with PnP better than pnpm in large monorepos?

Not in my benchmarks. Yarn Berry PnP has an interesting disk advantage but the compatibility cost is higher than pnpm's. On top of that, TypeScript tooling and IDEs have more stable support for pnpm's model than for PnP. For new monorepos in 2026, pnpm is the more pragmatic bet.

Did npm 10 improve enough that switching isn't worth it?

npm 10 improved quite a bit — workspaces work well, installs are faster than npm 8. But on disk and cold CI, the gap with pnpm is still substantial (610 MB vs 1.4 GB in my case). If you've got everything configured with npm and don't have a concrete disk or build time problem, the migration might not be worth the cost. If you're starting a new project, start it with pnpm.

How do I handle dependency updates in pnpm with a monorepo?

pnpm update --recursive --latest updates all apps and packages in the workspace at once. What I learned to do is run this on a separate branch, run the full build, and review lockfile changes before merging. With strict TypeScript, broken type changes show up in the build — which is exactly the safety net I described in the post about functional programming in TypeScript.


My final take (and what I don't buy about the viral benchmarks)

pnpm wins in 2026. That's not up for debate after seeing the numbers in real production. But the "just migrate and you're done" narrative that circulates in viral HN posts feels dishonest to me — or written by someone who's never run pnpm against Shadcn/ui with an outdated version of Radix UI.

The real cost of adopting pnpm isn't install time or learning the CLI. It's the day something breaks in production because a transitive dependency was relying on flat hoisting and nobody documented it. That day exists. It happened to me. It's fixable — but you need to know it's coming.

What I don't buy: that Yarn Berry is relevant for new projects in 2026 without a very specific use case. And I don't buy that shamefully-hoist=true is a valid solution — it's postponing the problem until someone on the team can't figure out why the monorepo behaves differently in local vs CI.

If you're coming from my same stack (Next.js 16, strict TypeScript, Shadcn/ui, Railway), the migration is worth it. Just do it with your eyes open: configure public-hoist-pattern for the UI scopes, cache the pnpm store in CI, and keep TypeScript strict as your safety net for when hoisting surfaces implicit dependencies. That's exactly what I'd do differently if I were starting from scratch.

In the meantime, if you're seeing weird "module not found" errors after migrating to pnpm, before you panic — check whether the package has its own dependencies properly declared. High probability the problem is upstream, not you.


Primary source:


This article was originally published on juanchi.dev