(前端工程化01)私人管家-包管理器

字数:3883, 阅读时间:10分钟,点击阅读原文
目录:

包管理器

在很久很久以前,那时候的前端被大家”亲切“的称为“切图仔”,那时前端的工作非常简单,仅仅只是将设计图还原,然后加上一些交互和特效。由于没有分享的平台,项目中很多自己写的东西分享出来也比较困难,代码的复用也只能是手动CV。即使用到了第三方的一些插件,比如jQuery,也只能下载后手动进行管理。

后来,nodejs出现了,作为一门后端语言,它的复杂程度远比前端要高得多,如果手动管理那将是一件很痛苦的事情,所以npm应运而生。

下面我们简单介绍一下几个概念:

  • 包:包即是一段能复用的代码,它可以存在开发者本地和云端,每个包可能依赖也可能不会依赖其他包
  • 包管理器:对包进行管理的工具,可以追溯包的版本、依赖、作者等相关信息,还可以将云端的包下载到本地。

NPM

npm即Node package Manager,软件开发者可在上面分享自己的成果,包含上百万个包,而且使用它可以轻松跟踪依赖和版本。

npm主要有三个部分组成:

  • 网站:开发者查找包(package)的主要途径,可以通过不同的条件进行检索,还可以管理自己或组织的账户
  • 注册表:一个巨大的数据库,保存了每个包(package)的相关信息
  • 命令行工具:通过命令行终端运行

NPM会在安装NodeJS的时候附带安装,具体的安装及配置请见上一篇《开发环境搭建》。

常用命令

生成配置文件package.json

npm init [配置]

配置:

  • -y(--yes) :跳过问答模式,所有配置全部选择默认配置

搜索包

npm search <包名>

注意: 搜索包需要切换到npm官方镜像源

npm包的开发门槛很低,数量众多,重复的轮子也多得出奇,每次选择一个包对我这种选择强迫症来说,不是一件容易的事情,一般我们可以参考以下几点:

  • 下载量,相信别人的选择
  • 维护的活跃程度,包括最后更新时间,是否可以给作者提交issues
  • 文档,没文档就是在看天书

安装包

npm install <包名> [配置] # install 可以简写为i

配置:

  • -g (--global):将包作为全局依赖安装,一般命令行工具之类的会选择此方式
  • -S (--save):将包作为生产依赖安装,一般在生成(线上)环境使用的依赖都采用此方式,默认也是此方式
  • -D (--save-dev):将包作为开发依赖安装,一般开发环境使用的一些工具都采用此方式安装

可以在包名后面加上版本号以安装特定版本号,如npm install vue@2.16.1

卸载包

npm uninstall <包名> [配置] 

配置和安装包配置一样,不同配置表示写在不同地方的包

更新包

npm update <包名> [配置] 

配置和安装包配置一样,不同配置表示写在不同地方的包

发布包

npm publish [配置]

配置:

  • --tag beta: 指定标签,默认为版本号,可使用npm publish --tag beta安装

安全检测

npm audit # 对包及其依赖进行安全监测,并生成报告
npm audit fix # 自动为易受攻击的依赖项安装兼容的更新
npm set audit false # 关闭监测机制

由于npm包的数量众多,而且很多包早已没有维护了,难免会出现一些安全问题,所以安全监测可以帮助我们做一些排查。

注意:** 安全监测需要切换到npm官方镜像源

清除缓存

npm cache clean --force #强制清除npm缓存

NPX

npm在5.2版本内置了npx工具,也可以使用npm install -g npx手动安装,主要用来在命令行调用项目内部安装的模块,避免安装一些全局模块。

  • 调用项目中安装的包

如果我们在项目中安装了gulp,要执行gulp相关的命令,如果在项目目录下在终端直接执行的话,它会去全局的包查找,如果要避免这种情况,就只能将命令定义在package.json的scripts中,然后通过npm run的方式来执行。如果使用npx,就会避免这种情况,因为它会优先去本地项目中寻找。

npx gulp --version
  • 避免全局安装模块

一般在使用一些脚手架的时候,我们需要在全局安装后才可使用。如果使用npx就不需要。

npx create-react-app my-react-app

npx 将create-react-app下载到一个临时目录,使用以后再删除,避免了安装全局模块。

  • 执行远程代码
# 执行 Gist 代码
$ npx https://gist.github.com/zkat/4bc19503fe9e9309e2bfaa2c58074d32

# 执行仓库代码
$ npx github:piuccio/cowsay hello

参考资料:npx 使用教程

package.json

package.json是npm的配置文件,一般存在于项目的根目录中,记录了当前工程信息及使用的依赖包信息。

必填字段
  • name:包的名字,不能以点(.)或下划线(_)开头,不能包含中文、大写字母及非URL安全字符,长度必须小于或等于214个字符,@开头的包标识它是Scoped包。
  • version:包的当前版本,遵循 Semantic Versioning 2.0.0 语义化版本规范
信息类字段
  • description:包的描述
  • keywords:关键字,值为一个字符串数组,当在搜索包时很有用
  • license:许可证,以便让用户了解他们是在什么授权下使用此包,以及此包还有哪些附加限制。
{
  "license": "MIT",
  "license": "(MIT or GPL-3.0)",
  "license": "SEE LICENSE IN LICENSE_FILENAME.txt",
  "license": "UNLICENSED"
}
链接类字段

各种指向项目文档、issues 上报,以及代码托管网站的链接字段。

  • homepage:是包的项目主页或者文档首页。
  • bugs:问题反馈系统的 URL,或者是 email 地址之类的链接。方便用户通过该途径向包作者反馈问题。
  • repository:是包代码托管的位置。
{
  "repository": { "type": "git", "url": "https://github.com/user/repo.git" },
  "repository": "github:user/repo",
  "repository": "gitlab:user/repo",
  "repository": "bitbucket:user/repo",
  "repository": "gist:a1b2c3d4e5f"
}
项目维护类字段

项目的维护者的相关信息。

  • `author:作者信息,一个人。
{
  "author": { "name": "Your Name", "email": "you@example.com", "url": "http://your-website.com" },
  "author": "Your Name <you@example.com> (http://your-website.com)"
}
  • `contributors:贡献者信息,可能很多人。
{
  "contributors": [
    { "name": "Your Friend", "email": "friend@example.com", "url": "http://friends-website.com" }
    { "name": "Other Friend", "email": "other@example.com", "url": "http://other-website.com" }
  ],
  "contributors": [
    "Your Friend <friend@example.com> (http://friends-website.com)",
    "Other Friend <other@example.com> (http://other-website.com)"
  ]
}
文件类信息

指定包含在项目中的文件,以及项目的入口文件。

  • files:项目包含的文件,可以是单独的文件、整个文件夹,或者通配符匹配到的文件。
{
  "files": [
    "filename.js",
    "directory/",
    "glob/*.{js,json}"
  ]
}
  • main:项目的入口文件。
{
  "main": "filename.js"
}
  • bin:随着项目一起被安装的可执行文件,开发命令行工具会用到此项。
{
  "bin": "bin.js",
  "bin": {
    "other-command": "bin/other-command"
  }
}
  • man:项目的入口文件。

项目的入口文件。

{
  "man": "./man/doc.1",
  "man": ["./man/doc.1", "./man/doc.2"]
}
  • directories:当你的包安装时,你可以指定确切的位置来放二进制文件、man pages、文档、例子等
{
  "directories": {
    "lib": "path/to/lib/",
    "bin": "path/to/bin/",
    "man": "path/to/man/",
    "doc": "path/to/doc/",
    "example": "path/to/example/"
  }
}
  • types:指定 TypeScript 中的类型声明文件
{
  "types": "./lib/main.d.ts",
}
任务类字段

脚本是定义自动化开发相关任务的好方法,比如使用一些简单的构建过程或开发工具。 在 scripts 字段里定义的脚本,可以通过npm run xxx 命令来执行。 例如,上述 build-project 脚本可以通过 npm run build-project 调用,并执行 node build-project.js

{
  "scripts": {
    "build-project": "node build-project.js"
  }
}

有一些特殊的脚本名称。 如果定义了 preinstall 脚本,它会在包安装前被调用。 出于兼容性考虑,installpostinstallprepublish 脚本会在包完成安装后被调用。

特定的 scripts
  • prepublish: 在打包并发布包之前运行,以及在没有任何参数的本地 npm 安装之前运行。
  • prepare: 在打包和发布包之前运行,在没有任何参数的本地 npm install 上运行,以及安装 git 依赖项时。 这是在 preublish 之后运行,但是在 preublishOnly 之前运行。
  • prepublishOnly: 在包准备和打包之前运行,仅限于npm发布。
  • prepack: 在打包 tarball 之前运行(在 npm packnpm publish,以及安装 git 依赖项时)
  • postpack: 在生成 tarball 之后运行并移动到其最终目标。
  • publish, postpublish: 在包发布后运行。
  • preinstall: 在安装软件包之前运行。
  • install, postinstall: 安装包后运行。
  • preuninstall, uninstall: 在卸载软件包之前运行。
  • postuninstall: 在卸载软件包之后运行。
  • preversion: 在改变包版本之前运行。
  • version: 改变包版本后运行,但提交之前。
  • postversion: 改变包版本后运行,然后提交。
  • pretest, test, posttest: 由 npm test 命令运行。
  • prestop, stop, poststop: 由 npm stop 命令运行。
  • prestart, start, poststart: 由 npm start 命令运行。
  • prerestart, restart, postrestart: 由 npm restart 命令运行。 注意:如果没有提供重启脚本,npm restart 将运行 stopstart 脚本。
  • preshrinkwrap, shrinkwrap, postshrinkwrap: 由 npm shrinkwrap 命令运行。
依赖描述类字段

记录了当前工程或者包的其他依赖,他们的版本遵循如下规则:

  • 补丁发布:1.01.0.x~1.0.4
  • 次要版本:11.x^1.0.4
  • 主要版本:*x
  • dependencies:这些是你的包的开发版和发布版都需要的依赖,使用npm i xxx -S安装。
{
  "dependencies": {
    "package-1": "^3.1.4",
    "package-2": "file:./path/to/dir"
  }
}
你可以指定一个确切的版本、一个最小的版本 (比如 >=) 或者一个版本范围 (比如 >= ... <)。
包也可以指向本地的一个目录文件夹。
  • devDependencies:这些是只在你的包开发期间需要,但是生产环境不会被安装的包,使用npm i xxx -D安装。

这些是只在你的包开发期间需要,但是生产环境不会被安装的包。

{
  "devDependencies": {
    "package-2": "^0.4.2"
  }
}

我们再安装包的时候最好按照使用环境来安装,不要不分环境随便安装,否则在某些情况下打包会出现问题。

参考资料: package.json 说明文档

package-lock.json

原则上,包的发布需要严格遵循 语义版本控制 规则,但是这并不是一个强制的规则,所以,大多人开发的时候经验会出现同样的 package.json 文件,但安装了不同版本的包,这可能导致出现一些兼容错误,所以npm在安装时就会生成lock来锁定版本。

查找规则

npm包在使用时遵循如下查找规则:

  1. 在当前目录下查找node_modules目录;如果没有则向上一层目录查找,如果也没有则继续向上层目录查找直到根目录; 如果都没有则报错
  2. 进入node_modules中查找模块名目录;如果没有则报错
  3. 进入模块名目录查找 package.json 文件中的 main 配置项,导入该配置项指定的文件
  4. 如果模块名目录中没有 package.json文件,或package.json文件中没有 main 配置项,则加载 index.js 文件

Yarn

Yarn 是一个由 Facebook,Google,Exponent 和 Tilde 构建的新的 JavaScript 包管理器。正如官方公告所写,它的目标就是解决这些团队使用 npm 的时候所遇到的几个问题,即:

  • 安装包不够快速和稳定
  • 存在安全隐患,因为 npm 允许包在安装的时候运行代码

它并不是想要完全替代 npm。Yarn 仅仅是一个能够从 npm 仓库获取到模块的新的 CLI 客户端。

更清晰的输出

yarn的输出很清晰,使用了emoji,看起来也更加漂亮。

并行安装

在安装多个包时,npm会按包顺序执行,也就是只有当一个包全部安装完成后,才会安装下一个。Yarn 则是并行执行任务,提高了性能。

yarn和npm的命令对比

  • 有区别的命令
Npm Yarn 功能描述
npm install(npm i) yarn install(yarn) 根据 package.json 安装所有依赖
npm i –save [package] yarn add [package] 添加依赖包
npm i –save-dev [package] yarn add [package] –dev 添加依赖包至 devDependencies
npm i -g [package] yarn global add [package] 进行全局安装依赖包
npm update –save yarn upgrade [package] 升级依赖包
npm uninstall [package] yarn remove [package] 移除依赖包
  • 相同操作的命令
Npm Yarn 功能描述
npm run yarn run 运行 package.json 中预定义的脚本
npm config list yarn config list 查看配置信息
npm config set registry 仓库地址 yarn config set registry 仓库地址 更换仓库地址
npm init yarn init 互动式创建/更新 package.json 文件
npm list yarn list 查看当前目录下已安装的node包
npm login yarn login 保存你的用户名、邮箱
npm logout yarn logout 删除你的用户名、邮箱
npm outdated yarn outdated 检查过时的依赖包
npm link yarn link 开发时链接依赖包,以便在其他项目中使用
npm unlink yarn unlink 取消链接依赖包
npm publish yarn publish 将包发布到 npm
npm test yarn test 测试 = yarn run test
npm bin yarn bin 显示 bin 文件所在的安装目录
yarn info yarn info 显示一个包的信息

yarn的命令跟npm的命令差异不大,如果使用过npm,那么过渡到yarn也很简单。npm本身也在不断优化,继续使用也没有关系。

参考资料:Npm vs Yarn 之备忘详单

未来

现在npm包还是有很多无法回避的问题,最初node_modules下面每个依赖包的依赖放在自己的目录下面,相同的依赖无法复用,不管是安装还是删除都非常低效,而且在windows上经常会出现因为超过最大嵌套层级而无法删除的情况,不过好在后来官方调整了架构,改为平铺的结构,解决了这些问题。

不过现阶段npm的包管理还是很混乱,我们经常会看到下面这张图:

  • npm现在有很多重复的包,很多不维护的包,这给使用者造成了困扰
  • npm依赖繁多,比如我就仅仅想开发一个react的demo,结果发现要安装上千个包

npm官方应该也意识到了,所以它们正在开发下一代包管理工具Tink,相信不久的将来就会和我们见面,是不是很期待呢?

原文链接:segmentfault.com

上一篇:Deno 钻研之术:(1) Hello,从多样化安装到简单实战
下一篇:Node.js URL模块

相关推荐

  • (前端工程化01)私人管家-包管理器

    字数:3883, 阅读时间:10分钟,点击阅读原文 目录: 磨刀篇-开发环境搭建 私人管家-包管理器 待续 包管理器 在很久很久以前,那时候的前端被大家”亲切“的称为“切图仔”,那时前...

    5 个月前
  • (前端工程化01)私人管家-包管理器

    字数:3883, 阅读时间:10分钟,点击阅读原文 包管理器 在很久很久以前,那时候的前端被大家”亲切“的称为“切图仔”,那时前端的工作非常简单,仅仅只是将设计图还原,然后加上一些交互和...

    5 个月前
  • 重新认识prettier及如何工程化

    背景 对前端代码进行格式化时大多数同学都用到过prettier,例如在vscode中安装prettier插件,即可格式化任意文件,或者只格式化文件的选中部分。 prettier起到的作用是按照统一...

    1 年前
  • 谈谈前端工程化 js加载

    当年的 js 加载 在没有 前端工程化之前,基本上是我们是代码一把梭,把所需要的库和自己的代码堆砌在一起,然后自上往下的引用就可以了。 那个时代我们没有公用的cdn,也没有什么特别好的方法来优化加载j...

    1 年前
  • 第22期 Recoil-Facebook官方React状态管理器 &amp; Facebook前端技术栈重构分享

    Recoil-Facebook官方React状态管理器 说到状态管理器,轮子满天飞。在 Class 时代,redux 与 mobx 几乎占据了全部市场,几乎没有没用过 redux 的同学。

    5 个月前
  • 拾遗记5-工程化补充

    npxnpx是npm 5.2版本之后附带的一个命令,通过npx可以解决项目开发过程中的问题。避免全局安装模块npm不提倡全局安装模块,全局安装会造成一些问题,主要问题如下:全局安装的模块会存放到本地的...

    2 个月前
  • 工程化下的SSR初探-降级渲染

    该文章阅读需要 7 分钟,更多文章请点击本人博客halu886 概念 思路 集成 Router 和 Store 抽象逻辑层 客户端激活 踩坑 总结 概念 在续上篇 ssr 骨架搭建之...

    6 个月前
  • 工程化——前端静态资源缓存策略

    增量更新是目前大部分团队采用的缓存更新方案,能让用户在无感知的情况获取最新内容。具体实现方式通常是(一般我们通过构建工具来实现,比如webpack): 构建产出文件hash(如:index.d94f...

    2 年前
  • 小菜鸡的成长之路(前端工程化)

    写在前面小菜鸡的我又来记录笔记了,这次是前端工程化,感觉现在的前端能做的事情很多,不仅仅是以前写写页面的切图仔了。大到编辑器、页面,小到服务端的增删改都可以去做,而且也不在拘于web端,app、桌面端...

    4 个月前
  • 安装 Homebrew - macOS下的软件包管理器

    安装了HomeBrew之后,可以使用简单的命令去安装macos下的大多数软件,如 brew install nginx 就可以很方便的安装nginx了。 Hombrew官网 Homebrew 會將 ...

    2 年前

官方社区

扫码加入 JavaScript 社区