← All Notes

Migrating Astro Projects from npm to pnpm

In a nutshell

cd /path/to/project

# Delete `node_modules` so pnpm creates its own dependency layout
rm -rf node_modules

# Delete package-lock.json so the project only uses pnpm-lock.yaml
rm -f package-lock.json

# Installs project dependencies
pnpm install

# run if pnpm reports ignored build scripts.
pnpm approve-builds

# run again after approving build scripts.
pnpm install

Notes:

  • Commit package.json, pnpm-lock.yaml, and any generated pnpm-workspace.yaml.
  • Do not commit package-lock.json.

pnpm-workspace.yaml

If pnpm creates pnpm-workspace.yaml for build approvals, add:

# Wait 10080 min (7 days) before installing newly published package versions.
minimumReleaseAge: 10080

Monorepo Astro project

Use this when the root has multiple apps, like:

project/
  package.json
  apps/
    site/
      package.json
    portal/
      package.json

From the root:

cd /path/to/project
rm -rf node_modules apps/site/node_modules apps/portal/node_modules
rm -f package-lock.json apps/site/package-lock.json apps/portal/package-lock.json

Create pnpm-workspace.yaml in the root:

# defines which folders are workspace projects.
packages:
# includes every direct app folder inside apps
  - "apps/*"

minimumReleaseAge: 10080

Then install:

pnpm install
pnpm approve-builds
pnpm install

Notes:

  • The root pnpm-workspace.yaml is what tells pnpm that apps/site and apps/portal are part of the workspace.

Monorepo package names

Each app should have a unique package name.

apps/site/package.json:

{
  "name": "@bagus-villas/site",
  "private": true
}

apps/portal/package.json:

{
  "name": "@bagus-villas/portal",
  "private": true
}

private: true because these are deployable apps, not packages I intend to publish.

Root scripts for monorepo

Root package.json:

{
  "name": "bagus-villas",
  "private": true,
  "scripts": {
    "dev:portal": "pnpm --filter @bagus-villas/portal run dev",
    "build:portal": "pnpm --filter @bagus-villas/portal run build",
    "preview:portal": "pnpm --filter @bagus-villas/portal run preview",
    "dev:site": "pnpm --filter @bagus-villas/site run dev",
    "build:site": "pnpm --filter @bagus-villas/site run build",
    "preview:site": "pnpm --filter @bagus-villas/site run preview"
  }
}

Run from the root:

pnpm dev:site
pnpm build:site
pnpm dev:portal
pnpm build:portal

pnpm dev:site is shorthand for pnpm run dev:site.

Upgrading Astro later

Run the Astro upgrade inside each Astro app, not from the monorepo root.

cd apps/site
pnpm dlx @astrojs/upgrade
pnpm build

cd ../portal
pnpm dlx @astrojs/upgrade
pnpm build