Intro
The Heroku Node.js buildpack now supports pnpm, an alternative dependency manager. Early Node.js application owners who've taken advantage of pnpm support have seen 10-40% faster install times compared to NPM on Heroku deployments. It’s an excellent choice for managing packages in the Node.js ecosystem because it:
- Minimizes disk space with its content-addressable package store.
- Speeds up installation by weaving together the resolve, fetch, and linking stages of dependency installation.
This post will introduce you to some of the benefits of the pnpm package manager and walk you through creating and deploying a sample application.
Prerequisites
Prerequisites for this include:
- A Heroku account (signup).
- A development environment with the following installed:
- Git
- Node.js (v18 or higher)
- Heroku CLI
If you don’t have these already, you can follow the Getting Started with Node.js - Setup for installation steps.
Initialize a new pnpm project
Let’s start by creating the project folder:
mkdir pnpm-demo
cd pnpm-demo
Since v16.13, Node.js has been shipping Corepack for managing package managers and is a preferred method for installing either pnpm or Yarn. This is an experimental Node.js feature, so you need to enable it by running:
corepack enable
Now that Corepack is enabled, we can use it to download pnpm and initialize a basic package.json
file by running:
corepack pnpm@9 init
This will cause Corepack to download the latest 9.x
version of pnpm and execute pnpm init
. Next, we should pin the version of pnpm in package.json
with:
corepack use pnpm@9
This will add a field in package.json
that looks similar to the following:
"packageManager":
"pnpm@9.0.5+sha256.61bd66913b52012107ec25a6ee4d6a161021ab99e04f6acee3aa50d0e34b4af9"
We can see the packageManager
field contains:
- The package manager to use (
pnpm
). - The version of the package manager (
9.0.5
). - An integrity signature that indicates an algorithm (
sha256
) and digest (61bd66913b52012107ec25a6ee4d6a161021ab99e04f6acee3aa50d0e34b4af9
) that will be used to verify the downloaded package manager.
Pinning the package manager to an exact version is always recommended for deterministic builds.
engines
field of package.json
in the same way we already do with npm and Yarn. See Node.js Support - Specifying a Package Manager for more details.
Create the demo application
We’ll create a simple Express application using the express
package. We can use the pnpm add command to do this:
pnpm add express
Running the above command will add the following to your package.json
file:
"dependencies": {
"express": "^4.19.2"
}
It will also install the dependency into the node_modules
folder in your project directory and create a lockfile (pnpm-lock.yaml
).
The pnpm-lock.yaml
file is important for several reasons:
- Our Node.js Buildpack requires
pnpm-lock.yaml
to enable pnpm support. - It enforces consistent installations and packages resolution between different environments.
- Package resolution can be skipped which enables faster builds.
Now, create an app.js
file in your project directory with the following code:
const express = require('express')
const app = express()
const port = process.env.PORT || 3000
app.get('/', (req, res) => {
res.send('Hello pnpm!')
})
app.listen(port, () => {
console.log(`pnpm demo app listening on port ${port}`)
})
When this file executes, it will start a web server that responds to an HTTP GET request and responds with the message Hello pnpm!
.
You can verify this works by running node app.js
and then opening http://localhost:3000/ in a browser.
So Heroku knows how to start our application, we also need to create a Procfile
that contains:
web: node app.js
Now we have an application we can deploy to Heroku.
Deploy to Heroku
Let’s initialize Git in our project directory by running:
git init
Create a .gitignore
file that contains:
node_modules
If we run git status
at this point we should see:
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
Procfile
app.js
package.json
pnpm-lock.yaml
nothing added to commit but untracked files present (use "git add" to track)
Add and commit these files to git:
git add .
git commit -m "pnpm demo application"
Then create an application on Heroku:
heroku create
Not only will this create a new, empty application on Heroku, it also adds the heroku
remote to your Git configuration (for more information see Deploying with Git - Create a Heroku Remote).
Finally, we can deploy by pushing our changes to Heroku:
git push heroku main
Conclusion
Integrating pnpm with your Node.js projects on Heroku can lead to more efficient builds and streamlined dependency management, saving time and reducing disk space usage. By following the steps outlined in this post, you can easily set up and start using pnpm to enhance your development workflow. Try upgrading your application to pnpm and deploy it to Heroku today.