Featured image of post Mac 开发环境管理最佳实践:Homebrew + fnm + corepack + uv

Mac 开发环境管理最佳实践:Homebrew + fnm + corepack + uv

Mac 开发环境管理最佳实践:Homebrew + fnm + corepack + uv

作为 CPS 专业的学生,你的 Mac 就是你最重要的生产工具。不同课程需要不同版本的 Node.js 和 Python,如果全局安装一个大版本,另一门课的项目可能直接跑不起来。这篇文章会带你用 四个工具 搭建一套干净、可复现、互不冲突的开发环境。

整体架构

先把全局图景放在脑海里,我们使用的工具链是这样的:

  flowchart TB
    subgraph 基础层
        HB[Homebrew<br/>macOS 包管理器]
    end

    subgraph 运行时管理层
        FNM[fnm<br/>Node.js 版本管理]
        UV[uv<br/>Python 版本管理]
    end

    subgraph 包管理器层
        CP[corepack<br/>pnpm/yarn 代理]
        PIP[uv 内置<br/>pip/venv 替代]
    end

    subgraph 项目层
        PJ1[项目 A<br/>Node 18 + Python 3.11]
        PJ2[项目 B<br/>Node 20 + Python 3.12]
    end

    HB --> FNM
    HB --> UV
    FNM --> CP
    CP --> PJ1
    CP --> PJ2
    FNM --> PJ1
    FNM --> PJ2
    UV --> PIP
    PIP --> PJ1
    PIP --> PJ2

核心理念:每一层只管一件事,版本切换在项目级别自动生效。

第一步:安装 Homebrew —— 一切的起点

Homebrew 是 macOS 事实上的包管理器,后面所有的工具都通过它安装。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

安装完成后,根据终端提示把 Homebrew 加入 PATH。如果你用的是 zsh(macOS 默认):

echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc
source ~/.zshrc

验证安装:

brew --version

类比:把 Homebrew 想象成你 Mac 上的「App Store 命令行版」。后面要装什么工具,一行命令搞定。

第二步:fnm —— 轻量级 Node.js 版本管理器

为什么不用 nvm?

nvm 是最老牌的 Node.js 版本管理器,但它有两个痛点:

  1. :每次打开终端都要 source 一大段 shell 脚本,明显拖慢启动速度。
  2. 纯 Shell 实现:不支持 Windows,团队协作时配置不统一。

fnm(Fast Node Manager)用 Rust 编写,启动速度快 40 倍以上,且支持跨平台。

安装

brew install fnm

然后在 ~/.zshrc 中添加初始化:

echo 'eval "$(fnm env --use-on-cd --shell zsh)"' >> ~/.zshrc
source ~/.zshrc

--use-on-cd 是关键参数:当你 cd 进一个包含 .node-version.nvmrc 的项目目录时,fnm 会自动切换到对应版本。

常用操作

# 安装最新的 LTS 版本
fnm install --lts

# 安装指定版本
fnm install 20
fnm install 18

# 查看已安装的版本
fnm list

# 切换版本
fnm use 20

# 设置默认版本
fnm default 20

# 在项目中固定 Node 版本(进入项目目录后执行)
echo "20" > .node-version

验证

node --version   # 应该显示 v20.x.x
npm --version    # 应该显示 10.x.x

第三步:corepack —— 零安装使用 pnpm

为什么用 pnpm 而不是 npm?

特性 npm pnpm
磁盘占用 每个项目独立存储 全局内容寻址存储,硬链接共享
安装速度 较慢 显著更快
幽灵依赖 有(扁平化 node_modules) 无(严格的依赖隔离)
Monorepo 支持 需要 workspaces 原生支持

对 CPS 学生来说,pnpm 的严格依赖管理能帮你避免很多「在我电脑上能跑」的经典问题。

启用 corepack

Corepack 是 Node.js 官方的包管理器代理,不需要单独安装,它随 Node.js 一起发布。你只需要启用它:

corepack enable

这会在你的 PATH 中注册 pnpmyarn 等命令的代理。当你运行 pnpm 时,corepack 会根据项目 package.json 中的 "packageManager" 字段自动下载并使用正确版本。

在项目中使用

# 使用 pnpm 初始化项目
pnpm init

# 固定 pnpm 版本(推荐,确保团队一致性)
corepack use pnpm@latest
# 这会在 package.json 中写入类似:
# "packageManager": "pnpm@9.15.1"

# 安装依赖
pnpm install

# 添加依赖
pnpm add express
pnpm add -D typescript

常用 pnpm 命令速查

pnpm add <pkg>          # 添加依赖
pnpm add -D <pkg>       # 添加开发依赖
pnpm run <script>       # 运行脚本
pnpm exec <cmd>         # 在项目上下文中执行命令
pnpm store prune        # 清理未引用的缓存包

第四步:uv —— 极速 Python 环境管理

为什么不用 conda / pyenv?

  • conda:重量级,base 环境容易污染,启动慢。
  • pyenv:编译安装 Python,在 macOS 上经常遇到 OpenSSL 编译问题。
  • uv:Astral 团队(Ruff 的创建者)出品,用 Rust 编写,安装 Python 快 10-100 倍,内置虚拟环境和包管理功能。

安装

brew install uv

管理 Python 版本

# 安装最新的 Python 3.12
uv python install 3.12

# 安装多个版本
uv python install 3.11 3.12 3.13

# 查看已安装的版本
uv python list --only-installed

# 查看可安装的版本
uv python list

为每个项目创建独立环境

# 进入项目目录
mkdir my-project && cd my-project

# 初始化项目(会创建 .python-version 和 pyproject.toml)
uv init

# 指定 Python 版本
uv python pin 3.12

# 创建虚拟环境并安装依赖
uv add flask
uv add --dev pytest

# 同步依赖(类似 pnpm install)
uv sync

关键概念uv python pin 会在项目目录生成 .python-version 文件,确保任何人 clone 这个项目后运行 uv sync 都能获得完全一致的环境。

常用 uv 命令速查

uv init                  # 初始化新项目
uv add <pkg>             # 添加依赖
uv add --dev <pkg>       # 添加开发依赖
uv remove <pkg>          # 移除依赖
uv sync                  # 同步环境(安装所有依赖)
uv run <cmd>             # 在虚拟环境中运行命令
uv python pin <version>  # 固定 Python 版本
uv python install <ver>  # 安装 Python 版本

第五步:项目级工作流示范

假设你这学期有两门课,分别需要不同的技术栈:

  flowchart LR
    subgraph "Web 开发课"
        A[.node-version: 20] --> B[package.json<br/>packageManager: pnpm@9]
        A --> C[.python-version: 3.12]
    end

    subgraph "数据科学课"
        D[.node-version: 18] --> E[package.json<br/>packageManager: pnpm@9]
        D --> F[.python-version: 3.11]
    end

Web 开发课项目

mkdir web-course-project && cd web-course-project

# Node 环境
echo "20" > .node-version
fnm install && fnm use
corepack enable
pnpm init
corepack use pnpm@latest

# Python 环境
uv init
uv python pin 3.12
uv add flask

数据科学课项目

mkdir data-course-project && cd data-course-project

# Node 环境
echo "18" > .node-version
fnm install && fnm use

# Python 环境
uv init
uv python pin 3.11
uv add numpy pandas matplotlib

当你 cd 切换项目目录时,fnm 和 uv 会自动切换到对应版本,无需任何手动操作。

常见问题

Q:fnm 和 corepack 会冲突吗?

不会。fnm 管理 Node.js 二进制文件,corepack 管理包管理器(pnpm/yarn)。它们分工明确,互不干扰。

Q:uv 能替代 pip 吗?

能。uv adduv pip install 都可以安装包,但推荐使用 uv add,因为它会自动更新 pyproject.tomluv.lock,保证可复现性。

Q:要不要把 node_modules 和 .venv 加入 .gitignore?

必须。这两个目录应该永远在 .gitignore 中:

node_modules/
.venv/
__pycache__/

依赖锁定文件(pnpm-lock.yamluv.lock必须提交到 Git,它们是环境可复现的保证。

Q:Homebrew Cask 是什么?

brew install 安装命令行工具,brew install --cask 安装 GUI 应用(如 VS Code、Docker Desktop)。两者都通过 Homebrew 管理。

brew install --cask visual-studio-code
brew install --cask docker

总结

工具 管理什么 安装方式 版本固定文件
Homebrew 系统级 CLI 工具 brew install Brewfile(可选)
fnm Node.js 版本 brew install fnm .node-version
corepack pnpm/yarn 版本 corepack enable package.json 中的 packageManager
uv Python 版本 + 包 brew install uv .python-version + uv.lock

记住这个原则:每个项目都有自己的版本文件,工具根据文件自动切换,全局永远保持干净。这样无论你有多少门课、多少个项目,环境都不会打架。

A winner is just a loser who tried one more time.
Robust AI
使用 Hugo 构建
主题 StackJimmy 设计