前端包管理器
前端包管理器
node包管理器
各种分支
npm(node package manager,node的包管理工具)
node package manager,下载更新node的时候会自动下载更新npm
一些常用命令
npm install # 根据 package.json 自动安装
npm install xxx # 或 npm i xxx
npm uninstall xxx
一些选项
--save
或-S
,添加到 package.json 的 dependencies 列表,运行时依赖--save-dev
或-D
,添加到 package.json 的 depDependencies 列表,开发时依赖--global
或-g
,安装到全局而不是本地@type/...
,配合TypeScript使用时,我们通常需要为第三方库安装类型定义文件。这可以使TypeScript理解库的类型并提供更好的智能感知。 另外,@type包一般属于开发时依赖,一般会使用--save-dev
进行安装...@next
,表示下一个预发布版本...@latest
,表示最近的稳定版本,注意不是last而是latest,都有“最近的”的意思
cnpm(淘宝npm镜像)
同步频率目前为 10分钟 一次以保证尽量与官方服务同步
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm支持npm除了publish之外的所有命令,所以说你可以放心的使用cnpm来代替npm使用,这样可能使用包管理的时候更加的方便,因为服务器就在国内。
npx
- npm
- 本身不能够执行任何包,对于本地项目的包,如果想要执行,则需要写入到 package.json 里面,然后通过 npm 来解析 package.json 文件,解析到包的 bin 文件路径,在 bash 中执行。
- npx
- 是一个工具,npm v5.2.0引入的一条命令(npx),一个npm包执行器,指在提高从npm注册表使用软件包时的体验 ,npm使得它非常容易地安装和管理托管在注册表上的依赖项,npx使得使用CLI工具和其他托管在注册表。
- 主要特点:
- 临时安装可执行依赖包,不用全局安装,不用担心长期的污染
- 可以执行依赖包中的命令,安装完成自动运行
- 自动加载node_modules中依赖包,不用指定$PATH
- 可以指定node版本、命令的版本,解决了不同项目使用不同版本的命令的问题
- 总结
- npx 为 npm 文件执行功能进行了一些扩展,提供了一种使用 node.js CLI 工具的新方式,这种方式比起以前的执行方式更加灵活,并且对于本地环境变量的污染更小(你可以到自己的 node 安装目录下看一下,有多少个 bin 目录下的软连接在污染你的环境变量)。指定包版本的功能可以让我们更灵活地测试一些新的功能,而不用进行升级和降级,还是能够带来很多方便的。
pnpm
快速的,节省磁盘空间的包管理工具。
官网中文说明:https://pnpm.io/zh/
yarn
使用
Yarn和npm命令对比
- < npm | (simp) | yarn
- npm install | npm i | yarn
- npm install taco --save | npm i taco | yarn add taco
- npm uninstall taco --save | npm un taco | yarn remove taco
- npm install taco --save-dev | npm i -D taco | yarn add taco --dev
- npm update --save | npm up | yarn upgrade
与Npm区别
参考:https://zhuanlan.zhihu.com/p/27449990
“Yarn是由Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具 ,正如官方文档中写的,Yarn 是为了弥补 npm 的一些缺陷而出现的。”
npm时的坑了:
npm install
的时候巨慢。特别是新的项目拉下来要等半天,删除node_modules,重新install的时候依旧如此。同一个项目,安装的时候无法保持一致性。由于package.json文件中版本号的特点,下面三个版本号在安装的时候代表不同的含义。
"5.0.3", "~5.0.3", "^5.0.3"
Yarn的优点:
速度快
并行安装
离线模式
安装版本统一
更简洁的输出
多注册来源处理
更好的语义化
不过有了yarn的压力之后,npm做了一些类似的改进。
- 默认新增了类似yarn.lock的 package-lock.json;
- git 依赖支持优化:这个特性在需要安装大量内部项目(例如在没有自建源的内网开发),或需要使用某些依赖的未发布版本时很有用。在这之前可能需要使用指定 commit*id 的方式来控制版本。
- 文件依赖优化:在之前的版本,如果将本地目录作为依赖来安装,将会把文件目录作为副本拷贝到 node*modules 中。而在 npm5 中,将改为使用创建 symlinks 的方式来实现(使用本地 tarball 包除外),而不再执行文件拷贝。这将会提升安装速度。目前yarn还不支持。
总结
在npm5.0之前,yarn的优势特别明显。但是在npm之后,通过以上一系列对比,我们可以看到 npm5 在速度和使用上确实有了很大提升,值得尝试,不过还没有超过yarn。
比较
GPT4
- npm(Node Package Manager)
- Node.js 默认的包管理器,也是全球最大的软件注册表
- 优点
- npm在Node.js安装的时候默认就已经包含了
- 提供npm scripts,一个非常有用的工具,可以帮助你运行和构建应用
- 缺点
- 国内时有网络问题,有鉴于此,国内出现了一些npm的镜像网站,例如cnpm
- 在npm v5之前,npm没有提供package-lock功能,意味着两次执行npm install可能会产生不同的node_modules
- cnpm
- cnpm是淘宝团队对npm进行一些改进后的版本,主要解决的是npm在中国大陆访问速度慢的问题。使用cnpm镜像可以大大提高npm模块的安装速度。
- 优点
- 安装速度快
- 安装的模块版本更稳定
- 缺点
- 不能直接使用npm的官方插件,需要通过插件的作者提供支持
- npx
- npx是npm v5.2.0引入的一种工具,可以帮助开发者更简单方便的运行npm包
- 优点
- 无需全局安装npm包,可以直接调用
- 可以直接从GitHub或者其他地方运行代码
- 可以指定不同版本的Node.js运行代码
- 缺点
- 使用npx可能会导致工作路径包含非常大的.node_modules目录
- 在某些情况下,npx可能不知道应该执行哪个命令
- pnpm
- pnpm是一个值得关注的npm客户端,它的安装策略与npm和yarn不同,pnpm通过使用硬链接和符号链接以一种新的方式存储模块
- 优点
- 节省磁盘空间和安装速度快
- 严格的包隔离,一个包只能访问它在package.json中声明的依赖关系,这使编写可移植和可靠的代码更加容易
- 缺点
- 由于其存储策略的特殊性,可能在一些项目中引发异常
- yarn
- yarn是由Facebook在2016年推出的,为了解决npm的一些问题,例如安装速度慢,package-lock.json不始终可靠等。由于yarn可以并行处理依赖关系,安装速度比npm快很多。并且yarn提供了一个稳定的lockfile和更直观的CLI输出等特性。
- 优点
- 安装速度快
- 默认生成lock文件,确保了依赖版本的一致性
- 可以并行执行任务,提高运行和安装速度
- 缺点
- 所需内存大
- 需要与你的项目和团队同步,并且需要新的配置步骤
冲突问题(FAQ)
GPT4
同时使用是否会有冲突?比如我已经选择了pnpm或npx,但遇到了一个库的官方推荐下载方法是npm,此时我是否能用回npm而不造成任何冲突?或反过来之前用npm,但有一个包他推荐用npx(yarn好像会和另外几个冲突?)
除了镜像,他们的源都是npm网站上的吗?能保证来源的一致性?
使用不同的包管理器可能会引发一些问题,但这通常是可以管理的。 例如,如果你使用pnpm或yarn,但是又需要使用npm安装某个包,是可以的。
只要注意管理好你的node_modules和package-lock文件以避免冲突。在相似的情形下,有一个包推荐使用npx,你也可以无冲突的使用,因为npx主要是用来执行命令,而不是管理项目的依赖性。关于yarn和其它包管理工具可能出现的问题,主要原因在于yarn有自己的一份lock文件(yarn.lock),所以如果在项目中混用yarn和npm可能会引起依赖管理的混乱。
对于npm、cnpm、npx、pnpm和yarn,他们的源都是由npm网站提供的,都指向相同的模块。他们的工作原理基本相同,下载和提取相同的包。
在大多数情况下,可以确保包的一致性。为了进一步保证一致性,一些管理器(如yarn和pnpm)提供了lock文件,记录了安装的每个包的确切版本,以确保无论在何时何地执行安装,都会得到完全一样的依赖。
镜像站(如cnpm)提供的包也是与npm保持同步的,但在短时间内可能存在一些延迟。
镜像的使用
(话说总感觉我的梯子对npm比较不友好,其他的github和google服务都比较流畅,npm老卡)
- cnpm,其实使用cnpm会更好(比指定镜像源快,可能会自动选择?),但是cnpm不能用于pnpm、yarn等
- 配置镜像源
npm get registry # 查询当前源
npm config set registry https://registry.npmmirror.com # 国内
npm config set registry https://registry.npmjs.org/ # 官方
# pnpm和yarn的语法完全一致,只要将`npm`修改成`pnpm`或`yarn`即可
- 单次临时使用
npm --registry https://registry.npm.taobao.org install XXX(模块名)
常用的npm镜像源:
- cnpm的默认源 https://registry.npmmirror.com
- 淘宝 https://registry.npm.taobao.org
- 腾讯 http://mirrors.cloud.tencent.com/npm/
- 如果记不住又不想用cnpm又不记得源,可以先
npm install cnpm
,再cnpm get registry
查 (好别扭)
坑:需要注意!!!哪怕使用 cnpm get registry
的相同源,结果可能也和cnpm不同!如下,cnpm能成功!但 --registry
指定了相同的源却只能下载较低版本的typescript版本!不知道为什么
PS H:\Git\Private\Group_FrontEnd\obsidian-node-flow2> npm --registry https://registry.npmmirror.com/ install -D typescript@^5.0.0
npm ERR! code ETARGET
npm ERR! notarget No matching version found for typescript@5.0.0.
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.
npm ERR! A complete log of this run can be found in: C:\Users\76269\AppData\Local\npm-cache\_logs\2024-10-19T08_40_07_711Z-debug-0.log
PS H:\Git\Private\Group_FrontEnd\obsidian-node-flow2> npm install -D typescript@^5.0.0
npm ERR! code ETARGET
npm ERR! notarget No matching version found for typescript@5.0.0.
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.
npm ERR! A complete log of this run can be found in: C:\Users\76269\AppData\Local\npm-cache\_logs\2024-10-19T08_40_57_066Z-debug-0.log
PS H:\Git\Private\Group_FrontEnd\obsidian-node-flow2> cnpm install -D typescript@^5.0.0
√ Linked 1 latest versions fallback to H:\Git\Private\Group_FrontEnd\obsidian-node-flow2\node_modules\.store\node_modules
√ Installed 1 packages on H:\Git\Private\Group_FrontEnd\obsidian-node-flow2
√ All packages installed (1 packages installed from npm registry, used 662ms(network 661ms), speed 1.33MB/s, json 1(898.07KB), tarball 0B, manifests cache hit 0, etag hit 0 / miss 1)
devDependencies:
+ typescript ^5.6.3
PS H:\Git\Private\Group_FrontEnd\obsidian-node-flow2> cnpm get registry
https://registry.npmmirror.com/
结构目录
基本目录
node_modules
目录是Node.js包管理器(npm或pnpm)安装的所有依赖包的默认存放位置。其基本的目录结构如下:
多个依赖包:
- /node_modules/
- package-1/
- ...
- package-n/
- @scoped-user/
- package-1/
- ...
- package-n/
每个依赖包都有自己的目录,命名为包名。如果包被发布在一个scope下(例如@typescript-eslint/eslint-plugin),那么它会在一个名为scope的目录下。
每个依赖包的目录
每个依赖包的目录下通常包含以下文件和文件夹:
- package-name/
- node_modules/, 这个包所需要的其他依赖包
- package.json, 描述包的元信息(如版本,依赖,入口文件等)
- index.js or package-main-field.js, 包的入口文件
- ..., 可选的其他文件
重复/加速管理
在大型项目中,相同的包可能在不同地方多次安装。为了避免重复,npm 和 pnpm 都提供了一种叫做hoisting
的机制,可以提升相同的包到更高的node_modules目录下。
同时,pnpm 通过 交叉链接(symlink)
和一个叫做 .pnpm
的全局存储层,来进一步避免重复和加速安装。
知识细节
原理
更多的命令参数
@
标志
在npm中,有@
开头的包通常表示它是一个命名空间包,也就是说它属于一个包的集合。这是npm的scoped packages特性,允许用户将相关的包组织在一起。
例如,@angular/core
,@angular/common
,@angular/forms
等都是Angular团队发布的包,他们都在@angular
这个命名空间下。
相比之下,没有@
开头的包是普通包,它们没有特定的命名空间。例如,express
,lodash
,moment
等。
这两种类型的包在功能和使用上没有本质区别,主要的区别在于组织和命名方式。使用命名空间的好处是,它可以避免包名冲突,使得包的组织更加清晰,并且可以更好地表示包之间的关系。
发布到npm仓库 (实例)
参考:https://www.bilibili.com/video/BV1MS4y1L7QW,以Vue封装组件并发布到npm仓库为例
项目准备
vue create my-app
npm run serve
新建 /src/package 文件夹,防止需要上传npm的组建
目录结构:
- /src/
- .../
- package/
- pig-button/
- index.vue
- pig-input/
- index.vue
- pig-button/
- index.js (需要创建这个来使用Vue install方法)
- App.vue
组件封装
使用Vue插件模式,会用到Vue提供的一个公开方法:install。这个方法会在使用 Vue.use(plugin)
时被调用。这样使我们的插件注册到全局,在子组件的任何地方都可以使用
index.js
import PigButton from "../package/pig-button/index.vue" // 引入封装好的组件
const coms = [PigButton]; // 将来如果有其他组件,可以写到这个数组里
// 批量组件注册
const install = function (Vue) {
coms.forEach((com) => {
Vue.component(com.name, com);
});
};
export default install; // 这个方法以后再使用的时候就可以被use调用
组件打包
修改 package.json 文件,配置打包命令:
"srcipts": {
"package": "vue-cli-service build --target lib ./src/package/index.js --name pig-ui --dest pig-ui";
// --target lib: 打包到的目录
// --name: 打包后的文件名字
// --dest: 打包后的文件夹的名称
}
然后打包
npm run package
发布到npm
cd /pig-ui/
# 里面也有一个 package.json,可以去修改里面的东西
# 注册npm账号
npm config set registry=https://registry.npmjs.org # 修改为官方源,避免自己之前改成了淘宝源
npm adduser # 添加 npm 用户
npm publish # 发布 npm
组件使用
可参考element-ui的用法
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI);
父组件
import PigUi form 'pig-ui-test2'
import 'pig-ui-test2/pig-ui.css'
Vue.use(PigUi)
子组件
<template>
<div id="app">
<pig-button></pig-button> <!--由于前面全局注册过了,这里直接使用就行了-->
</div>
</template>
实战技巧:pnpm workspace 管理 monorepo
详见 [../子项目构建系统/pnpm monorepo] 笔记