理解现代 Web 技术栈:Babel
版本信息和存储库
(本教程使用Babel v7编写,但一般概念适用于任何版本)
您可以在此处找到“了解现代 Web 堆栈”教程系列的官方存储库。
这包含每个教程代码示例的最终版本,以确保您没有遗漏任何内容。您也可以提交 Pull 请求,以纠正您发现的任何错误或更正(我会相应地更新博客文章)。
目录
Babel 是什么?
Babel 是一款工具,它允许您使用所有最新的语法和功能编写 JavaScript 代码,并在可能不支持这些功能的浏览器中运行。Babel 是一个转译器,可以将您当前的 JS 代码转换为更多浏览器能够理解的旧版 JavaScript 代码。
Babel 通常内置于我们日常构建现代 Web 应用程序的工具中(例如create-react-app),因此许多开发者并不完全了解该工具的实际功能。本教程旨在逐步讲解 Babel 的配置,它是构建自定义开发环境系列教程的一部分。
先决条件
你需要在你的机器上安装Node.js并可以在终端中使用。安装 Node的同时会自动安装npm ,而 npm 正是你安装 Babel 时使用的。
打开你选择的终端。如果你在运行以下两个命令时看到版本号(你的版本号可能与本例不同),那么你就可以开始了:
node --version
> v15.5.0
npm --version
> 7.16.0
初始化项目
让我们从初始化一个新npm
项目开始。运行以下命令来生成一个:
npm init -y
该-y
标志将自动为所有内容选择默认值,这在我们的示例中是合适的。
接下来,让我们使用一些现代语法创建一个非常基本的 Javascript 文件。script.js
使用以下代码创建一个名为 的文件:
script.js
const x = 5;
let y;
const sampleFunction = () => "this is a return value";
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const hasThree = [1, 2, 3].includes(3);
console.log(hasThree);
y ||= "a new value";
console.log(y);
在上面的例子中const
,,,let
数组方法和都是ES6arrow function
的功能,它们无法在旧版浏览器中正常运行,例如(不幸的是,即使在 2021 年,一些组织仍在广泛使用这些浏览器)。includes
class
Internet Explorer 11
您可能还会遇到全新的(截至 2021 年)逻辑或赋值。它无法在 Firefox 79 之前的版本和 Chrome 85 之前的版本中运行,并且根本无法在 IE11 中运行。
那么,我们怎样做才能在旧版浏览器上运行此代码,而不必自己重写它呢?
安装 Babel
为了实现我们的目标,我们需要三个基本软件包,它们都是 Babel 生态系统的一部分,但每个都有不同的功能。首先运行以下命令:
npm install @babel/core @babel/cli @babel/preset-env --save-dev
让我们看看每个人在做什么:
@babel/core
- 这是主引擎,它知道如何根据给定的一组指令转换代码@babel/cli
- 这是我们将要运行的实际程序,用于触发核心引擎并输出转换后的 Javascript 文件@babel/preset-env
- 这是一个预设,用于告诉核心引擎需要进行哪些类型的转换。它会package.json
根据您希望支持的浏览器,检查您的环境(在我们的例子中是我们的配置文件)来确定需要进行哪些类型的更改。
我们需要在文件中添加几个值package.json
:
browserslist
- 这告诉 Babel 我们的目标浏览器是哪些。浏览器越老/支持越少,Babel 就需要做越多的工作和转换才能让你的应用程序在这些浏览器中正常工作。语法是一个简单的字符串数组。你可以在这里了解更多。babel
- 我们在这里定义了所有要使用的预设,以及与这些预设相关的配置选项。我们将从最简单的一个开始,@babel/preset-env
所以我们的package.json
文件应该是这样的:
package.json
{
"devDependencies": {
"@babel/cli": "^7.15.7",
"@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.6"
},
"browserslist": ["last 2 Chrome versions"],
"babel": {
"presets": [["@babel/preset-env"]]
}
}
您的应该devDependencies
已经存在了npm install
。上面描述的另外两个属性需要您自行添加。
转换你的代码
其最基本的配置babel
将把您的现代语法转换为更广泛支持的ES5。
package.json
让我们从一个简单的例子开始。在包含你的文件和文件的项目根目录中运行以下命令script.js
:
npx babel script.js --out-file script-transformed.js
假设您已经遵循了到目前为止的所有说明,您应该会看到一个名为 的新文件,script-transformed.js
如下所示:
script-transformed.js
"use strict";
const x = 5;
let y;
const sampleFunction = () => "this is a return value";
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const hasThree = [1, 2, 3].includes(3);
console.log(hasThree);
y ||= "a new value";
console.log(y);
没什么区别吧?除了添加严格模式之外,实际上没有任何变化。
原因在于我们如何在中配置我们的环境package.json
,这就是@babel/preset-env
我们决定应该做什么的地方。
package.json
...
"browserslist": [
"last 2 Chrome versions"
],
...
由于我们仅针对最新的 2 个版本的 Chrome,因此 Babel 知道我们可以毫无问题地包含我们想要的所有现代 JS 语法,它将在这些现代浏览器中正常运行。
但是假设我们需要支持Internet Explorer 11
。我们不想仅仅为了适应那个浏览器而改变代码编写方式,幸运的是,Babel 帮了大忙。更新你的package.json
代码,将 IE11 添加到browserslist
数组中:
...
"browserslist": [
"last 2 Chrome versions",
"IE 11"
],
...
现在再次运行此命令:
npx babel script.js --out-file script-transformed.js
看看这次的输出:
script-transformed.js
"use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var x = 5;
var y;
var sampleFunction = function sampleFunction() {
return "this is a return value";
};
var Person = function Person(name, age) {
_classCallCheck(this, Person);
this.name = name;
this.age = age;
};
var hasThree = [1, 2, 3].includes(3);
console.log(hasThree);
y || (y = "a new value");
console.log(y);
这看起来和我们的原始文件大相径庭!注意,ES6
我们上面讨论的几乎所有术语都消失了,const
被替换为var
,箭头函数被替换为function
语法,并且我们的class
已经转换为一个基本的Javascript对象。现在我们可以把这个script-transformed.js
文件上传到服务器,Internet Explorer 11
它就可以正常运行了……差不多了!
我们还有一个小问题:includes
方法没有被转换。为什么呢?要理解原因,我们首先需要理解polyfills
。
Polyfills
要理解为什么我们需要,我们必须理解什么是新的和什么是新的polyfills
之间的区别。方法是新的。它背后有自己的逻辑,简单地改变代码的语法并不能向老版本的浏览器解释该方法的逻辑应该如何运行。syntax
functionality
includes
functionality
includes
对于引入新功能的新功能,我们需要一个叫做polyfill的东西。polyfill 只是一些方法的源代码,includes
你可以将它与应用程序捆绑在一起,以便教会旧版浏览器如何使用它。
您无需自行编写 polyfill,几乎所有 JS 功能的 polyfill 都已存在,并且易于添加。在后续的教程中,我们将讲解如何打包并仅添加我们需要的特定功能,但在此之前,我们只需添加一个名为core-js的库,即可立即让我们的应用访问所有现代 JS 功能,即使在旧版浏览器上也是如此。
为了测试一下,我们将整个库加载core-js
到我们的应用中。由于我们还没有使用打包器,所以我们只需minified
从 Web 加载已经打包好的版本即可。如果您还没有index.html
模板,请在项目根目录中创建此文件:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script src="script-transformed.js"></script>
</head>
<body></body>
</html>
(如果您不确定如何提供此文件,请先运行并查看输出,查看本教程)
我们首先尝试在 IE11 中加载该文件。如果您的机器没有安装 Internet Explorer 11,可以直接按照此处的示例操作。此示例在Windows 11
已完全移除 IE11 的浏览器中运行。幸运的是, IE 11Microsoft Edge
附带了IE 11 模式,可用于测试需要向后兼容的应用程序。
当我们运行 Babel 并尝试在 IE11 中加载我们的script-transformed.js
文件时,我们在控制台上收到以下错误:
现在,让我们将core-js
库添加到我们的 中的<script>
标签中。您可以在此处找到最新的最小化包 URL 。<head>
index.html
index.html
...
<head>
<meta charset="UTF-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.18.1/minified.js"></script>
<script src="script-transformed.js" defer></script>
</head>
...
当我们在 IE11 中重新加载页面时,我们得到:
成功了!我们正在编写现代 JavaScript,并在一个老旧的浏览器中运行它!太棒了!
总结
现在你应该已经扎实掌握了 Babel 的基本概念及其工作原理。当然,还有更多内容有待探索。在未来的教程中,我们将深入探讨 Babel 支持的另外两个用于转译 JavaScript 超集的主要预设:JSX和Typescript。
当我们开始使用时,webpack
我们还将研究如何配置 Babel,以便它仅从core-js
您在应用程序中实际使用的大型库(如Array.includes()
)中导入那些函数,这样您就不需要包含整个库本身。
请查看本系列的其他文章!如果您觉得其中任何一篇有帮助,欢迎留言或提问,并与他人分享:
Twitter 上的@eagleson_alex
感谢您的阅读,敬请期待!
鏂囩珷鏉ユ簮锛�https://dev.to/alexeagleson/building-a-modern-web-stack-babel-3hfp