4、Node.js npm离线安装:npm pack打包、npm cache离线利用、npm离线仓库verdaccio搭建

说实话,Node.js 的 npm 生态虽然方便,但一到内网环境就让人头疼。我经历过好几次——项目急着上线,结果服务器连不上外网,npm install 直接卡死。那种感觉,你懂的。

今天我就把几种靠谱的离线安装方案掰开揉碎了讲。从最简单的单包打包,到搭建企业级离线仓库,一条龙给你安排明白。

4.1 方案一:npm pack 打包——最直接的单包搬运

如果你只需要安装一两个包,npm pack 是最快的方式。说白了,就是把一个 npm 包压缩成 .tgz 文件,然后拿到内网去解压安装。

4.1.1 打包操作

在有网的机器上执行:

# 打包单个包
npm pack express

# 打包指定版本
npm pack express@4.18.2

# 打包后生成 express-4.18.2.tgz

嗯,这里要注意:npm pack 只会打包你指定的那个包,不会自动包含它的依赖。我刚开始用的时候就被坑过——把包拷到内网,一安装发现缺了一堆依赖。

避坑指南: 我曾经因为没打包依赖,在内网折腾了整整一下午。记住,npm pack 只打包当前包,依赖需要单独处理。

4.1.2 离线安装

把 .tgz 文件拷贝到内网机器,然后:

# 直接安装 tgz 文件
npm install ./express-4.18.2.tgz

# 或者解压后安装
tar -xzf express-4.18.2.tgz
cd package
npm install

我个人习惯用第一种方式,省事。但如果你要安装的包依赖很多,这个方法就不太合适了。

4.2 方案二:npm cache 离线利用——批量依赖的救星

当项目依赖几十上百个包时,一个个打包显然不现实。这时候,npm cache 就派上用场了。

4.2.1 缓存原理

npm 在安装包时,会把下载的包缓存到本地。默认路径是 ~/.npm 目录。你想想看,既然本地有缓存,那能不能直接把缓存搬到内网?

答案是:可以,但有技巧。

4.2.2 缓存导出与导入

在有网的机器上:

# 先安装项目依赖,生成缓存
npm install

# 查看缓存位置
npm cache ls

# 导出缓存(npm v6+)
npm cache ls --cache ./npm-cache-backup

# 或者直接打包 .npm 目录
tar -czf npm-cache.tar.gz ~/.npm

然后到内网机器:

# 解压缓存
tar -xzf npm-cache.tar.gz -C ~/

# 设置离线模式安装
npm install --prefer-offline --no-audit --no-fund
小技巧: 加上 --prefer-offline 参数,npm 会优先使用缓存,只有缓存没有时才去网络下载。在内网环境,这个参数能避免很多超时问题。

4.2.3 缓存目录结构

npm 缓存的结构是这样的:

~/.npm/
├── _cacache/          # 主要缓存目录
│   ├── content-v2/    # 包内容
│   └── index-v5/      # 索引
└── _locks/            # 锁文件

我记得有一次,同事直接把整个 ~/.npm 目录拷贝到内网,结果 npm install 还是去联网。后来才发现,_cacache 目录的权限不对。嗯,拷贝时记得保持文件权限。

4.3 方案三:verdaccio 搭建离线仓库——企业级解决方案

如果你需要长期维护内网环境,或者团队多人协作,搭建一个私有 npm 仓库才是正道。我个人最推荐 verdaccio,轻量、好配、功能全。

4.3.1 verdaccio 是什么?

verdaccio 是一个轻量级的 npm 私有仓库。它支持:

  • 缓存代理:第一次从外网下载,之后从缓存提供
  • 私有包发布:团队内部包可以发布到本地
  • 权限控制:可以设置谁可以发布、谁可以安装
  • 离线可用:缓存过的包,断网也能安装

4.3.2 安装与配置

安装 verdaccio 很简单:

# 全局安装
npm install -g verdaccio

# 启动(默认端口 4873)
verdaccio

启动后,访问 http://localhost:4873 就能看到仓库界面。但默认配置只适合开发环境,生产环境需要调整。

配置文件一般在 ~/.config/verdaccio/config.yaml,我常用的配置:

# 存储路径
storage: ./storage
# 插件目录
plugins: ./plugins

# 上游 registry
uplinks:
  npmjs:
    url: https://registry.npmjs.org/
    # 缓存超时时间(毫秒)
    cache: true
    max_fails: 10
    timeout: 60s

# 包访问权限
packages:
  '@*/*':
    access: $all
    publish: $authenticated
    proxy: npmjs

  '**':
    access: $all
    publish: $authenticated
    proxy: npmjs

# 监听地址
listen:
  - 0.0.0.0:4873

# 开启离线模式
offline: false
关键点: uplinks 里的 cache: true 一定要开。这样第一次从外网下载后,包会缓存到本地 storage 目录。之后即使断网,也能从缓存安装。

4.3.3 离线仓库的初始化

搭建好 verdaccio 后,需要先「预热」缓存。我的做法是:

# 1. 设置 npm 指向本地仓库
npm set registry http://内网IP:4873

# 2. 在有网环境下,安装项目依赖
npm install

# 3. 此时所有依赖都被缓存到 verdaccio 的 storage 目录
# 4. 把 storage 目录打包,拷贝到内网服务器
tar -czf verdaccio-storage.tar.gz ~/.config/verdaccio/storage

到了内网,解压 storage 目录,启动 verdaccio,团队就能直接离线安装了。

4.3.4 团队使用配置

团队成员只需要修改 npm 配置:

# 设置 registry
npm set registry http://内网IP:4873

# 或者使用 .npmrc 文件
echo "registry=http://内网IP:4873" > .npmrc

然后正常执行 npm install 即可。如果包已经在缓存中,安装速度会非常快。

注意: 如果内网完全与外网隔离,记得把 config.yaml 里的 uplinks 部分注释掉,或者设置 offline: true。否则 verdaccio 会尝试连接外网 registry,导致超时。

4.4 三种方案对比

方案 适用场景 优点 缺点
npm pack 单包或少量包 简单直接,无需额外工具 依赖需单独处理,不适合大型项目
npm cache 单个项目批量依赖 利用现有缓存,无需搭建服务 缓存目录大,权限问题多
verdaccio 团队协作、长期维护 功能完善,支持私有包和权限控制 需要额外搭建和维护

4.5 核心流程总结

下面这张图,把三种方案的流程串起来了。你可以根据实际情况选择:

npm 离线安装三种方案流程 外网环境(有网) 内网环境(无网) 方案一:npm pack npm pack express → express.tgz 拷贝 npm install ./express.tgz 方案二:npm cache npm install → 生成 ~/.npm 缓存 拷贝缓存 npm install --prefer-offline 方案三:verdaccio 搭建 verdaccio → 预热缓存 拷贝 storage 启动 verdaccio → npm install 选择建议 • 临时用一次 → npm pack(最快最省事) • 单个项目离线 → npm cache(利用现有缓存) • 团队长期使用 → verdaccio(一劳永逸) ⚠ 无论哪种方案,都要提前规划好依赖清单

4.6 我的经验总结

做了这么多年运维,我踩过的坑不少。给你几个实在的建议:

  • 先列依赖清单:用 npm ls --depth=0 查看顶层依赖,再用 npm ls --all 看全量依赖。心里有数再动手。
  • 版本锁死:内网环境一定要用 package-lock.json 或 npm-shrinkwrap.json。否则同样的包名,内外网版本不一致,够你查半天的。
  • 测试验证:离线安装完成后,跑一遍 npm test 或 node -e "require('你的包')"。确保所有依赖都正常。
  • 定期更新缓存:如果使用 verdaccio,建议每个月在有网环境更新一次缓存,把新版本的包同步进来。

好了,这三种方案够你应对大部分离线场景了。从单包到企业级,按需选择就行。