npm 是什么,以及网站改完为什么要等一两分钟
npm 是什么
npm 是 JavaScript 世界里的包管理器,位置相当于 Python 的 pip。
它常和另外两样东西一起被提到,需要分开看:
| 名称 | 是什么 | 类比 |
|---|---|---|
| Node.js | 让 JavaScript 脱离浏览器运行的运行时 | Python 解释器 / JVM |
| npm(命令) | 随 Node 一起装上的包管理工具 | pip |
| npm(仓库) | 全球最大的公开包仓库 npmjs.com | PyPI |
前端几乎所有的工具和库都通过 npm 分发,Astro、Vite、Tailwind、ESLint 都是。想在项目里用任何一个,都得走 npm。下载时也不是零散地拿,而是一个包连带它依赖的一整串包一起装——这个博客第一次 npm install 就装了 342 个包,其中绝大多数是 Astro 依赖的依赖。
三个文件要认识
package.json:声明项目依赖哪些包、有哪些可执行脚本,相当于requirements.txtpackage-lock.json:锁定每个包的精确版本,保证任何机器装出来都一样,相当于poetry.locknode_modules/:包真正下载到的位置,可以随时删掉重装,相当于site-packages
node_modules 体积很大,从来不提交到 Git,.gitignore 已经把它排除在外。
博客用到的命令只有三条
npm install 读 package.json,把依赖装进 node_modules/
npm run build 执行构建,生成 dist/ 里的静态网页
npm run dev 起本地开发服务器,用来预览
npm run xxx 做的事很简单:去 package.json 的 scripts 里找 xxx 对应的命令并执行,可以理解成项目自定义的命令别名。
有一个容易被忽略的地方:这个博客的正式构建并不发生在本地。真实链路是
本地写 Markdown → 推到 GitHub → Cloudflare 服务器执行 npm install + npm run build → 发布静态网站
所以只写文章的话,本机根本不需要 npm;只有在本地预览或自己构建时才用得上。之前在本地跑的 npm install、npm run build,都只是为了让改动先在本地验证一遍。
为什么改完要等一两分钟
这是一个静态站,内容在构建那一刻就已经写进 HTML 里了。改一个字,整套流水线要重跑一遍:
- 提交推到 GitHub
- Cloudflare 收到通知,进入构建队列,可能还要排队
- 克隆仓库
npm install,重新下载那 342 个包npm run build,重新生成全部 HTML- 产物上传,分发到全球 CDN 的各边缘节点
这几步加起来一两分钟。这段时间里网站一直正常服务,只是发出去的还是上一版,直到新版全部铺完。
那 B 站为什么能”实时”
B 站走的是另一条路,页面不预先生成。打开时先拿到一个几乎不变的页面骨架,骨架里的脚本再去调接口取数据,后端查缓存或数据库,当场返回最新结果。数据本来就是请求那一刻才查出来的,因此永远是最新的,也就没有”等构建”这一环。
它也不是真的零延迟,只是把延迟藏在了用户感知不到的地方:
- 不常变的东西(图片、脚本、页面骨架)走 CDN
- 数据库前面加一层 Redis 缓存,避免每次请求都落到数据库
- 点赞、弹幕、播放量这类不要求立刻一致的数据,进消息队列异步处理
所以 B 站的播放量偶尔慢半拍、评论区偶尔显示”正在加载”,都是同一套机制的自然结果。
两者的差别
| 静态站(这个博客) | 动态站(B 站) | |
|---|---|---|
| 内容在哪 | 构建时写进 HTML | 请求时从数据库查 |
| 更新方式 | 改内容后重新构建、重新发布 | 改数据后立即生效 |
| 更新延迟 | 一两分钟 | 毫秒级 |
| 打开速度 | 极快,CDN 直接返回成品 | 骨架快,数据异步加载 |
| 成本 | 极低,CDN 静态文件近乎免费 | 高,需要数据库、缓存、多台服务器 |
| 个性化 | 做不到,所有人同一份 | 可以,千人千面 |
为什么选了慢的那条
一篇博客文章可能几天都不改动一次,为它常驻数据库和服务器并不划算。静态站换来的东西很实在:打开快、几乎零成本、没有服务器可以被攻击。
真正需要补救的只有一件事——改完想立刻看到效果。这个已经用本地即时预览解决了:保存后当前页面直接换成新内容,不用等构建。如果将来评论这类数据也要求实时,再单独把少数页面改成动态渲染即可,其余页面继续维持静态。