javascript原理

by Shubheksha

通过Shubheksha

JavaScript程序包管理器工作原理简介 (An introduction to how JavaScript package managers work)

A few days ago, ashley williams, one of the leaders of the Node.js community, tweeted this:

几天前,Node.js社区的负责人之一Ashley Williams在推特上发布了以下内容:

I didn’t really understand what she meant, so I decided to dig in deeper and read about how package managers work.

我不太了解她的意思,所以我决定更深入地研究并了解软件包管理器的工作方式。

This was right when the newest kid on the JavaScript package manager block — Yarn — had just arrived and was generating a lot of buzz.

当JavaScript程序包管理器块中的最新成员Yarn刚到并引起大量关注时,这是正确的。

So I used this opportunity to also understand how and why Yarn does things differently from npm.

因此,我利用这次机会也了解了Yarn的工作方式和原因以及与npm不同的原因 。

I had so much fun researching this. I wish I’d done so a long time ago. So I wrote this simple introduction to npm and Yarn to share what I’ve learned.

研究这个过程我非常开心。 我希望我很久以前就做过。 因此,我向npm和Yarn撰写了这个简单的介绍,以分享我所学到的知识。

Let’s start with some definitions:

让我们从一些定义开始:

什么是包裹? (What is a package?)

A package is a reusable piece of software which can be downloaded from a global registry into a developer’s local environment. Each package may or may not depend on other packages.

软件包是可重用的软件,可以从全局注册表中下载到开发人员的本地环境中。 每个程序包可能取决于也可能不取决于其他程序包。

什么是包管理器? (What is a Package Manager?)

Simply put — a package manager is a piece of software that lets you manage the dependencies (external code written by you or someone else) that your project needs to work correctly.

简而言之,程序包管理器是一款软件,可以让您管理项目正常运行所需的依赖项 (由您或其他人编写的外部代码)。

Most package managers juggle the following pieces of your project:

大多数程序包管理器会处理您的项目的以下部分:

项目编号 (Project Code)

This is the code of your project for which you need to manage various dependencies. Typically, all of this code is checked into a version control system like Git.

这是项目的代码,您需要为其管理各种依赖关系。 通常,所有这些代码都被检入到版本控制系统(如Git)中。

清单文件 (Manifest file)

This is a file that keeps track of all your dependencies (the packages to be managed). It also contains other metadata about your project. In the JavaScript world, this file is your package.json

这是一个跟踪所有依赖项(要管理的程序包)的文件。 它还包含有关您的项目的其他元数据。 在JavaScript世界中,此文件是您的package.json

依赖码 (Dependency code)

This code constitutes your dependencies. It shouldn’t be mutated during the lifetime of your application, and should be accessible by your project code in memory when it’s needed.

此代码构成您的依赖项。 它不应在应用程序的生命周期内进行更改,并且在需要时应由内存中的项目代码进行访问。

锁定档案 (Lock file)

This file is written automatically by the package manager itself. It contains all the information needed to reproduce the full dependency source tree. It contains information about each of your project’s dependencies, along with their respective versions.

该文件由程序包管理器本身自动写入。 它包含再现完整依赖项源树所需的所有信息。 它包含有关项目每个依赖项的信息,以及它们各自的版本。

It’s worth pointing out at this point that Yarn uses a lockfile, while npm doesn’t. We’ll talk about the consequences of this distinction in a bit.

值得指出的是,Yarn使用锁文件,而npm则没有。 我们将稍等一下这种区别的后果。

Now that I’ve introduced you to the parts of a package manager, let’s discuss dependencies themselves.

现在,我已经向您介绍了包管理器的各个部分,让我们自己讨论依赖项。

平面依赖与嵌套依赖 (Flat versus Nested Dependencies)

To understand the difference between the Flat versus Nested dependency schemes, let’s try visualizing a dependency graph of dependencies in your project.

为了了解Flat和Nested依赖方案之间的区别,让我们尝试可视化项目中依赖关系的依赖关系图。

It’s important to keep in mind that the dependencies your project depends on might have dependencies of their own. And these dependencies may in turn have some dependencies in common.

重要的是要记住,项目所依赖的依赖项可能具有自己的依赖项。 这些依赖关系可能又有一些共同之处。

To make this clear, let’s say our application depends on dependencies A, B and C, and C depends on A.

为了清楚起见,假设我们的应用程序依赖于依赖项A,B和C,而C依赖于A。

平面依赖 (Flat Dependencies)

As shown in the image, both the app and C have A as their dependency. For dependency resolution in a flat dependency scheme, there is only one layer of dependencies that your package manager needs to traverse.

如图所示,应用程序和C都具有A作为依存关系。 为了在平面依赖关系方案中解决依赖关系,包管理器仅需要遍历一层依赖关系。

Long story short — you can have only one version of a particular package in your source tree, as there is one common namespace for all your dependencies.

简而言之,您的源代码树中只能有一个特定程序包的版本,因为所有依赖项都有一个通用的命名空间。

Suppose that package A is upgraded to version 2.0. If your app is compatible with version 2.0, but package C isn’t, then we need two versions of package A in order to make our app work correctly. This is known an Dependency Hell.

假设软件包A已升级到2.0版。 如果您的应用程序与版本2.0兼容,但程序包C不兼容,则我们需要程序包A的两个版本才能使我们的应用程序正常工作。 这就是所谓的依赖地狱。

嵌套依赖 (Nested Dependencies)

One simple solution to deal with the problem of Dependency Hell is to have two different versions of package A — version 1.0 and version 2.0.

解决依赖关系地狱问题的一种简单解决方案是拥有包A的两个不同版本-版本1.0和版本2.0。

This is where nested dependencies come into play. In case of nested dependencies, every dependency can isolate its own dependencies from other dependencies, in a different namespace.

这是嵌套依赖项起作用的地方。 在嵌套依赖关系的情况下,每个依赖关系都可以在不同的名称空间中将其自身的依赖关系与其他依赖关系隔离。

The package manager needs to traverse multiple levels for dependency resolution.

程序包管理器需要遍历多个级别以解决依赖关系。

We can have several copies of a single dependency in such a scheme.

在这种方案中,我们可以具有单个依赖项的多个副本。

But as you might have guessed, this leads to a few problems too. What if we add another package — package D — and it also depends on version 1.0 of package A?

但是,您可能已经猜到了,这也会导致一些问题。 如果我们添加另一个软件包D,又取决于软件包A的版本1.0,该怎么办?

So with this scheme, we can end up with duplication of version 1.0 of package A. This can cause confusion, and takes up unnecessary disk space.

因此,使用这种方案,我们最终可能会复制软件包A的1.0版。这可能导致混乱,并占用不必要的磁盘空间。

One solution to the above problem is to have two versions of package A, v1.0 and v2.0, but only one copy of v1.0 in order to avoid unnecessary duplication. This is the approach taken by npm v3, which reduces the time taken to traverse the dependency tree considerably.

解决上述问题的一种方法是拥有软件包A的两个版本,即v1.0和v2.0,但是只有一个v1.0副本,以避免不必要的重复。 这是npm v3采取的方法 ,它大大减少了遍历依赖关系树的时间。

As ashley williams explains, npm v2 installs dependencies in a nested manner. That’s why npm v3 is considerably faster by comparison.

正如ashley williams解释的那样, npm v2以嵌套方式安装依赖项 。 因此,相比之下,npm v3的速度要快得多。

确定性与非确定性 (Determinism vs Non-determinism)

Another important concept in package managers is that of determinism. In the context of the JavaScript ecosystem, determinism means that all computers with a given package.json file will all have the exact same source tree of dependencies installed on them in their node_modules folder.

包管理器中的另一个重要概念是确定性。 在JavaScript生态系统的上下文中,确定性意味着所有具有给定package.json文件的计算机都将在它们的node_modules文件夹中安装完全相同的依赖源树。

But with a non-deterministic package manager, this isn’t guaranteed. Even if you have the exact same package.json on two different computers, the layout of your node_modules may differ between them.

但是对于不确定的软件包管理器,这是无法保证的。 即使您在两台不同的计算机上具有完全相同的package.json ,它们之间的node_modules布局也可能有所不同。

Determinism is desirable. It helps you avoid “worked on my machine but it broke when we deployed it” issues, which arise when you have different node_modules on different computers.

确定性是可取的。 它可以帮助您避免“在我的机器上工作但在部署它时就node_modules 了”的问题,该问题在不同的计算机上具有不同的node_modules时出现。

npm v3, by default has non-deterministic installs and offers a shrinkwrap feature to make installs deterministic. This writes all the packages on the disk to a lockfile, along with their respective versions.

默认情况下,npm v3具有非确定性安装,并提供拆封功能以使确定性安装成为可能。 这会将磁盘上的所有软件包及其各自的版本写入到一个锁文件中。

Yarn offers deterministic installs because it uses a lockfile to lockdown all the dependencies recursively at the application level. So if package A depends on v1.0 of package C, and package B depends on v2.0 of package A, both of them will be written to the lockfile separately.

Yarn提供确定性安装,因为它使用锁定文件在应用程序级别上递归锁定所有依赖项。 因此,如果程序包A依赖于程序包C的v1.0,而程序包B依赖于程序包A的v2.0,则这两个程序将分别写入锁定文件。

When you know the exact versions of the dependencies you’re working with, you can easily reproduce builds, then track down and isolate bugs.

当您知道正在使用的依赖项的确切版本时,您可以轻松地复制生成,然后跟踪并隔离错误。

“To make it more clear, your package.json states “what I want” for the project whereas your lockfile says “what I had” in terms of dependencies. — Dan Abramov

“为了更加清楚,您的package.json声明了项目的“我想要什么” ,而锁文件就依赖项说了“我拥有什么” 。 — 丹·阿布拉莫夫

So now we can return to the original question that started me on this learning spree in the first place: Why is it considered a good practice to have lockfiles for applications, but not for libraries?

因此,现在我们可以回到最初引发学习狂的原始问题: 为什么为应用程序而不是库拥有锁文件被认为是一种好习惯?

The main reason is that you actually deploy applications. So you need to have deterministic dependencies that lead to reproducible builds in different environments — testing, staging, and production.

主要原因是您实际上在部署应用程序。 因此,您需要具有确定性的依存关系,以在不同的环境(测试,登台和生产)中生成可复制的构建。

But the same isn’t true for libraries. Libraries aren’t deployed. They’re used to build other libraries, or in application themselves. Libraries need to be flexible so that they can maximize compatibility.

但是对于库来说并非如此。 未部署库。 它们用于构建其他库,或用于应用程序本身。 库需要灵活,以便最大程度地实现兼容性。

If we had a lockfile for each dependency (library) that we used in an application, and the application was forced to respect these lockfiles, it would be impossible to get anywhere close to a flat dependency structure we talked about earlier, with the semantic versioning flexibility, which is the best case scenario for dependency resolution.

如果我们为应用程序中使用的每个依赖项(库)都有一个锁定文件,并且应用程序被迫遵守这些锁定文件,那么就不可能通过语义版本控制接近我们之前讨论的平面依赖关系结构。灵活性,这是解决依赖项的最佳方案。

Here’s why: if your application has to recursively honor the lockfiles of all your dependencies, there would be version conflicts all over the place — even in relatively small projects. This would cause a large amount of unavoidable duplication due to semantic versioning.

原因是:如果您的应用程序必须递归地使用所有依赖项的锁定文件,那么即使在相对较小的项目中,到处也会存在版本冲突。 由于语义版本控制,这将导致大量不可避免的重复。

This is not to say that libraries can’t have lockfiles. They certainly can. But the main takeaway is that package managers like Yarn and npm — which consume these libraries — will not respect those lockfiles.

这并不是说库不能有锁文件。 他们当然可以。 但是主要的收获是,使用这些库的Yarn和npm之类的程序包管理器将不遵守这些锁定文件。

Thanks for reading! If you think this post was useful, please tap the “︎❤” to help to promote this piece to others.

谢谢阅读! 如果您认为这篇文章有用,请点按“︎❤”以帮助将此文章推广给其他人。

翻译自: https://www.freecodecamp.org/news/javascript-package-managers-101-9afd926add0a/

javascript原理

javascript原理_JavaScript程序包管理器工作原理简介相关推荐

  1. 以rpm为后端及以yum为前端工具的程序包管理器在Linux发行版系统centos中的使用...

    程序包管理: 应用程序的安装,实际上是解压缩并复制程序包中的文件到指定目录的过程: 程序包管理器: 方便终端用户进行程序的安装.卸载.升级.安装信息查询及校验等工作: 不同的Linux的发行版本中,有 ...

  2. Windows 程序包管理器 1.0 正式发布

    在 Microsoft Build 2021 开发者大会上,微软正式发布 Windows Package Manager(程序包管理器)1.0 正式版,目前在 GitHub 上已有超过 1600 个程 ...

  3. 程序包管理器控制台 Add-Migration 用法

    需要注意的是: 1.任何对数据库的操作都在代码和程序包管理控制台完成,千万不要自己去修改数据库,no! 2.ef中创建数据库的表必须要有主键~!否则 就不让你成功~ 现在来说如何映射 第一步创建在代码 ...

  4. 通过程序包管理器控制台解决版本错误(CS1705)

    目录 介绍 背景 解决方案示例 介绍 如果解决方案中有多个项目,而一个项目依赖于其他项目,并且版本引入了重大更改,我们有时会遇到包版本冲突,并且Visual Studio解决方案无法构建.它可能会返回 ...

  5. Kubernetes之(二十)Helm程序包管理器

    目录 Kubernetes之(二十)Helm程序包管理器 概念 部署Helm 下载helm 部署Tiller helm的使用 chart 目录结构 chart模板 定制安装 MySQL chart c ...

  6. nuget找不到System.Windows.Forms时用程序包管理器控制台直接下载

    步骤如下图 下图即程序包管理器控制台 然后输入 Install-Package System.Windows.Forms -Version 4.0.0 这个下载代码来自NuGet

  7. 程序包管理器控制台在哪

    在安装有NuGet插件的VS上打开NuGet命令窗口的过程如下:依次选择菜单Tools(工具)->Library Package Manager(库程序包管理器)->Pakcage Man ...

  8. 怎么用nuget程序包管理器安装jquery_Nuget服务器

    搭建Nuget服务端 在Microsoft Visual Studio的空ASP.NET Web应用程序项目安装NuGet.Server,并以方式文件发布项目. 1.1.Vs中新建ASP.NET We ...

  9. Snap 程序包管理器被爆Linux 提权漏洞

     聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 Canonical 公司旗下产品 Snap 软件封装和部署系统中出现多个漏洞,其中最严重漏洞可被用于提权,获得root权限. Snaps 是自包 ...

最新文章

  1. 【按住你的心】——Android开发CheckBoxRadioButton控件的简单使用
  2. hybris impex里忽略某列数据的语法
  3. Requests库网络爬虫实战
  4. 安卓开发怎么调用photopicker_谷歌出手整顿安卓应用程序乱象:无良权限的APP们再见了!...
  5. html几个数据包,报文和数据包的区别
  6. 正则 (?i,m,s,x,g)
  7. javascript 函数2——对象排序
  8. Kubernetes实践:使用k8s部署微服务应用
  9. spss 25 的pls安装
  10. C语言4位BCD码加法器,四位二进制8421BCD码加法器
  11. (Java实现)洛谷 P1093 奖学金
  12. 俄勒冈之旅_欢迎美好的一天俄勒冈观众-消灭糖尿病2007
  13. linux查看目录增大了多少g命令,Linux中查看各文件夹大小命令
  14. 关于ping命令出现大量dup原因
  15. ubuntu 命令行批量重命名文件夹
  16. H3C交换机DHCP Snooping抑制局域网内非法dhcp
  17. NRF52832学习笔记(23)——GAP主机端连接
  18. 将svn diff改成用vimdiff命令进行可视化差异显示
  19. python --安装pylab
  20. 自己装修需要做好哪些准备?极家精装好不好?

热门文章

  1. 安装JDK1.8+环境配置
  2. python的基本知识点
  3. 《疯狂Java讲义》学习笔记(十)异常处理
  4. strust2自定义interceptor的基本方法及操作
  5. System.Web.Caching.Cache类 缓存 各种缓存依赖
  6. 友盟数据—值得手游创业者关注的玩家数据
  7. 修改Activity响应音量控制键修改的音频流
  8. Oracle 10g配置RMAN RECOVERY CATALOG
  9. 显示所有文件和文件夹无论如何 无法被设置
  10. 扫码下单支持同桌单人点餐FAQ