(前端工程化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": "./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的命令对比

  • 有区别的命令
NpmYarn功能描述
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 –saveyarn upgrade [package]升级依赖包
npm uninstall [package]yarn remove [package]移除依赖包
  • 相同操作的命令
NpmYarn功能描述
npm runyarn run运行 package.json 中预定义的脚本
npm config listyarn config list查看配置信息
npm config set registry 仓库地址yarn config set registry 仓库地址更换仓库地址
npm inityarn init互动式创建/更新 package.json 文件
npm listyarn list查看当前目录下已安装的node包
npm loginyarn login保存你的用户名、邮箱
npm logoutyarn logout删除你的用户名、邮箱
npm outdatedyarn outdated检查过时的依赖包
npm linkyarn link开发时链接依赖包,以便在其他项目中使用
npm unlinkyarn unlink取消链接依赖包
npm publishyarn publish将包发布到 npm
npm testyarn test测试 = yarn run test
npm binyarn bin显示 bin 文件所在的安装目录
yarn infoyarn info显示一个包的信息

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

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

未来

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

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

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

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

原文链接:segmentfault.com

上一篇:面试官:说说执行上下文吧
下一篇:5大顶尖数字货币交易所(合约交易)换肤方案浅谈

相关推荐

  • (本人)2019前端校招经历

    我是一个想要找前端工作的妹纸,最近电话面了挺多企业,在每次面试中都会发现自己的不足或者没涉及到的方面,一边被拒一边学习新知识。想要在这里记录、分享前端校招遇到的问题,希望每一次都有提升,下一次不会再犯...

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

    字数:3883, 阅读时间:10分钟,点击阅读原文 目录: 磨刀篇开发环境搭建 私人管家包管理器 待续 点击查看源网页(/public/upload/7b9b054b364e1627547...

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

    字数:3883, 阅读时间:10分钟,点击阅读原文 目录: 磨刀篇开发环境搭建 私人管家包管理器 待续 点击查看源网页(/public/upload/fde96d7941fadecf7f3...

    2 个月前
  • 阿里2019 校招 前端面试

    在10月初的时候投递了阿里校招之后,在十月中旬的时候终于接到了初面的邀请。 本来预约的是英国时间早上10点,但是突然接到面试组的电话,询问我是否可以提前到9点,我说可以就赶紧洗漱准备面试了。

    8 个月前
  • 错误:不能;找不到预设的“es2015”相对目录”/用户/用户名”

    错误:不能;找不到预设的“es2015”相对目录”/用户/用户名”...

    2 年前
  • 重新认识prettier及如何工程化

    1qdyIUswy9X5SxSR2tzrIJw.png(https://img.javascriptcn.com/93f429f947421085617d8d16a2017b3e "1qdyIUswy...

    7 个月前
  • 都9012年了,我还不理解VUE生命周期?

    前言 前两天为了准备一场面试,小韭菜紧张的不行。身边好多朋友有过面试官的经验,于是找他们演练了一番。果然小韭菜还是小韭菜... 被问到VUE的生命周期? 我一想,这简单呀,就那个图嘛,八个生命...

    7 个月前
  • 都 9012了,该选择 Angular、React,还是Vue?

    转载请注明出处:葡萄城官网(https://www.grapecity.com.cn/),葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 139239201904181526...

    1 年前
  • 邀好友赢大奖!快来抽取你的 2019 新年上上签!

    还有不到一个星期,2019 年就将正式「官宣」。值此之际,七牛云特别推出【好运好礼】新年上上签活动~不仅有好运好彩头,还有超多惊喜好礼等你拿。天猫购物卡、七牛云产品优惠包、樱桃机械键盘、终极大奖 iP...

    2 年前
  • 迟来的2018总结之一个有仪式感的2019启航

    IT平头哥联盟,苏南的专栏,专注于分享前端、测试 等领域的积累,文章来源于自己/群友工作中积累的经验、填过的坑,希望能尽绵薄之力 助其他同学少走一些弯路,苏南的专栏,书籍,码农书籍,前端开发、Reac...

    1 年前

官方社区

扫码加入 JavaScript 社区