Published on

搞懂 npm、npx 与 package.json

Authors
  • avatar
    Name
    Terry
    Twitter

无论是搭建脚手架还是管理项目依赖,npm 生态几乎贯穿前端工程化的整个流程。本文结合整理的资料,梳理 npm、npx 以及 package.json 的关键概念,帮助自己也帮助后来者在需要时迅速回顾。

参考资料

npm

npm 是 Node.js 官方提供的包管理器,让 JavaScript 开发者可以快速共享、安装和更新第三方包。它可以拆分为两大部分:

  • 用于发布、下载与管理包的 CLI(命令行界面)。
  • 存放所有包及其版本的在线 Registry。

npm 本身不会直接执行软件包,而是提供工具去调用它们。如果希望运行某个命令,需要显式指定可执行文件,或在 package.jsonscripts 字段中声明。

当安装带有可执行文件的依赖时,npm 会自动为这些命令创建可执行链接:

  • 本地安装会在 ./node_modules/.bin/ 下生成链接;
  • 全局安装则会链接到全局 bin 目录(例如 Linux 的 /usr/local/bin,Windows 的 %AppData%/npm)。

因此,如果刚执行 npm install prettier,可以通过以下方式运行本地安装的 prettier

./node_modules/.bin/prettier . --check

更推荐的做法是在 package.json 中定义脚本,这样团队成员只需要记住脚本名称即可:

{
  "name": "your-application",
  "version": "1.0.0",
  "scripts": {
    "prettier:check": "prettier . --check",
    "prettier:write": "prettier . --write"
  }
}

随后使用 npm run prettier:checknpm run prettier:write 即可。

npx

npx 的目标是让我们在不关心路径的情况下运行项目依赖或一次性脚手架命令。

调用项目内部依赖

仍以上面的 prettier 为例,有了 npx 后可以直接键入:

npx prettier . --check

npx 会先在当前项目的 node_modules/.bin 中查找命令,其次再到环境变量 PATH 中查找。这也意味着系统内置命令同样可以通过 npx 调用,例如 npx ls 等同于 ls

执行未安装的软件包

当只想临时体验某个包时,没必要先全局安装。npx 会把该包下载到临时目录,执行完自动清理,既方便也不占磁盘空间。利用这一点,可以轻松测试同一工具的不同版本,或运行一些一次性的 CLI。

package.json

每个 JavaScript 项目都可以被视为一个 npm 包,而 package.json 就是描述这个包的“说明书”。运行 npm init 初始化项目时,npm 会为你生成一个基础版本。

package.json 是项目的配置中心:npm(以及 Yarn 等工具)根据它来识别项目、安装依赖、运行脚本、发布到 Registry,并在整个生命周期里维护这些信息。

常见字段非常多,官方文档始终是最权威的参考:Specifics of npm's package.json handling。下面记录几个日常最常遇到的部分。

main

{
  "main": "src/index.js"
}

main 指定包的默认入口。当其他人执行 require('your-package') 时,就会返回这个文件导出的内容。

scripts

scripts 字段允许声明一组命令,所有脚本都可以通过 npm run <name> 触发。npm 预置了 pre<name>post<name> 钩子,便于在主脚本前后串联额外逻辑:

{
  "scripts": {
    "prebuild": "echo run before build",
    "build": "cross-env NODE_ENV=production webpack",
    "postbuild": "echo run after build"
  }
}

执行 npm run build 时会依次运行 prebuildbuildpostbuild。我们也可以添加自定义脚本,例如 "prepare": "husky install"

dependencies 与 devDependencies

  • dependencies:生产环境运行时必备的依赖。
  • devDependencies:仅在开发或构建阶段需要的工具,例如构建脚本、测试库。部署到生产时可以通过 npm install --production 跳过这些包,以缩小体积。

其他常见字段

  • peerDependenciesoverrides 等高级字段在特定场景下非常有用,遇到问题时按关键词搜索官方文档即可。
  • 你也可以在 package.json 中添加自定义字段,用于存储工具或团队需要的额外信息,例如:
{
  "name": "angular-love-pdf",
  "version": "0.0.0",
  "lint-staged": {
    "**/*": "prettier --write --ignore-unknown"
  }
}

总结

要搞懂前端工程化,首先要熟悉 npm 的包管理能力、npx 的命令执行技巧,以及 package.json 中常见字段的意义。整理这些概念的过程,也让我再次厘清它们在日常开发中的角色。