如果您5年前问我什么JavaScript Bundler是什么,我可能会告诉您,人们在几个小时里与之抗争,只是为了设置一个简单的Web应用程序,而这可能在2018年一直接近真相,直到今天,JavaScript生态系统发生了很多变化。
如果您开始进行网络开发旅程,或者可能已经潜入其中,但不确定JS捆绑器是什么以及它们的角色,您会阅读适当的解释。
混乱和复杂性 - 问题
让我们考虑一个非常简单的JavaScript应用程序。我们只有一页index.html
。我们的HTML用index.js
文件水合,这为其增加了一些交互性。为了使用它,我们需要在index.html
文件中导入index.js
脚本。我们还决定使用外部库(bootstrap),因此我们还应该链接必要的CSS。
我们将index.js
与script
标签链接在head
部分:
<head>
<script type="module" src="index.js"></script>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
crossorigin="anonymous"
/>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My WebPage</title>
</head>
当然,当我们构建一个Web应用程序时,我们不会将所有JavaScript代码放在index.js
中。这就是为什么我们创建了两个具有某些功能的单独文件:my-utils.js
和navigation.js
。
例如,my-utils.js
导出了一些功能:
export function doSomethingNice() {
alert("Nice!");
}
export function notUsedFunctionA() {
alert("Not used function A");
}
export function notUsedFunctionB() {
alert("Not used function B");
}
export function notUsedFunctionC() {
alert("Not used function C");
}
请注意,那里未使用的功能 - 我们很快就会达到他们的意义。
接下来,我们的index.js
文件导入所需的内容,并为HTML元素添加一些交互性:
import { doSomethingNice } from "./my-utils.js";
import { reloadThePage } from "./navigation.js";
document
.getElementById("reload-page-btn")
.addEventListener("click", reloadThePage);
document
.getElementById("say-sth-nice-btn")
.addEventListener("click", doSomethingNice);
如果我们现在打开网页,我们可以在加载页面时看到网络活动:
请注意,所有3个JavaScript文件均分别获取:index.js
,my-utils.js
和navigation.js
。
更重要的是,如果您检查my-utils.js
的内容,它显然会加载整个脚本,甚至包含未使用的功能:
我认为,当您拥有数百个自己的JavaScript文件加上数十个外部库时,您可能已经觉得这可能会遇到一些问题。您的应用程序不仅会提出数百个网络请求以获取每个文件,而且它将始终获取所有内容,即使您的页面都没有使用。
在这里,JavaScript Bundler进入了现场。
您可以找到此JavaScript App here的完整源代码。
JavaScript Bundler做什么?
javascript bundler产生捆绑包ð,但是什么是捆绑包?它基本上是一个静态文件,已优化可用于客户端(在我们的情况下:Web浏览器)。主要目标是从多个依赖项中产生一个捆绑文件。实际上,用户的浏览器不需要单独获取这么多文件。但是如何创建这样的捆绑包?
首先,JavaScript Bundler需要知道入口点。这是我们的代码树开始的一种根。如果我们从上一段中的示例JavaScript应用程序进行了示例JavaScript应用程序,那么入口点的理想候选者将是index.js
文件。现代捆队支持多个入口点。如果您重新构建乘法应用程序,则可能非常有用,因此每个页面都可以具有自己的入口点。
下一步是创建依赖关系图。 JavaScript Bundler基本上是从根部(入口点)开始,并遍历从中引用的所有依赖项以及所有这些依赖关系的依赖性。拥有依赖关系图,Bundler知道我们的应用程序的哪些以及哪个位置确切使用了什么。
这就是您可以想象依赖图的图:
像webpack这样的模块捆绑器不仅知道您的入口点的依赖项。这些工具甚至检查每个依赖性使用的用途。由于构建了这样的详细依赖图,Bundler可以在捆绑文件中引入多个优化。
最后,JavaScript Bundler输出实际捆绑包。正如我提到的,可以通过应用code splitting,CSS inlining,HMR和各种性能优化等技术来高度优化捆绑包。
JavaScript Bundler还可以通过将您的代码中使用的一些较新的JavaScript构造转换为以前的JS版本的等效物来确保与较旧的Web浏览器的向后兼容。
有趣的是,现代捆绑机不仅可以处理JS文件,还可以处理CSS,HTML甚至图像。
JavaScript Bundler在行动
目前,最受欢迎的JavaScript捆绑包是(仍然)webpack。它是为浏览器和nodejs创建的第一个真正高级的捆绑器。
您可能已经听到了有关WebPack的不愉快的事情,实际上,它的配置确实可以得到 spaghetti ðIT,那里有更简单的替代方案,但是让我们从S开始当今Web开发中使用的最常见工具。
将WebPack添加到JavaScript应用
我们的示例应用程序已经有一个package.json
文件(我们使用JavaScript模块),因此我们可以使用此命令安装WebPack:
npm install --save-dev webpack webpack-cli
现在,我们应该重新组织一些文件。让我们将所有脚本放在src
文件夹中,然后将index.html
移至dist
文件夹。最后,看起来这样:
使用名为dist
的文件夹非常常见。它代表分销,这意味着准备分发的代码=向公众提供。这是我们的捆绑包所在的地方。由于index.html
直接向公众提供,我们也将其放在那里。
有了这样的文件夹结构,我们不再需要配置WebPack才能工作。默认情况下,WebPack查找我们已经拥有的src/index.js
文件,并将捆绑包到dist
文件夹中。要使用更高级的功能或多个入口点,configuration file should be added。
在我们的情况下,让我们采用零孔方法。我们唯一需要的是将script
条目添加到package.json
:
"scripts": {
"build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
让我们现在运行npm run build
,看看会发生什么:
似乎WebPack创建了main.js
资产(捆绑):
让我们确保我们的index.html
页面正确链接了此捆绑文件:
<!DOCTYPE html>
<html lang="en">
<head>
<script type="module" src="main.js"></script>
现在,让我们打开我们的index.html
页面,看看网络请求现在的样子:
哇,这与我们以前的东西不同!请注意,现在只有1个脚本,即main.js
文件,由网页获取。以前有3个:index.js
,my-utils.js
和navigation.js
。当然,该网页正常工作。
让我们还检查获取的main.js
文件的内容:
请注意这里发生的事情。 WebPack已将我们直接使用的所有外部代码很好地列入了main.js
捆绑包。更重要的是,在这里根本不存在导出的my-utils.js
的功能!构建依赖关系图时,WebPack注意到没有使用这些功能,因此不包括它们ð
这基本上是WebPack和大多数JavaScript串件的工作方式。他们的作用是提供最小和最优化的捆绑包。最终,通过避免客户浏览器否则需要制作的不必要的网络请求来节省很多带宽。删除未使用的代码会使捆绑包较小,再次减少了网络使用。
您可以找到WebPack应用程序here的完整源代码。
Webpack还有更多可提供的
从当今使用的所有JavaScript捆绑包中,WebPack是最先进的。这也是最成熟的。它提供了数十种自定义,plugins和loaders。您也可以轻松添加TypeScript支持。
您可以使用WebPack做到真正疯狂的事情,但是,如果您开始进行网络开发旅程,请不要通过学习所有内容来淹没。请注意,WebPack几乎可以完成您可能需要的一切。这只是searching StackOverflow的问题或询问Copilotð
WebPack的替代方案
近年来,开发人员创建了其他一些令人惊叹的JavaScript捆绑包。我建议您注意他们,因为WebPack不必是您今天的首选。 WebPack仍然是used in CRA,这被认为是创建新的React应用程序的默认方式。这就是使其非常广泛使用的原因,但是您不需要遵循此路径ð
我建议检查Parcel,esbuild和ViteJS。这些是现代的捆绑机,以及其他一些捆绑包的负担。如果您刚开始并且不想让自己忙于捆绑配置,我特别建议使用包裹创建下一个应用程序。
概括
这就是您需要了解的有关JavaScript捆绑器的所有知识,以便能够与他们合作并了解执行此Magic npm run build
Script的情况