构建工具介绍
什么是构建工具
当你创建一些复杂的web应用时,性能就变得非常重要
你需要配置应用使其在不同的浏览器或低网速下正常工作,手动完成这些很困难,但是构建工具可以帮助你自动化这个过程
这是几种类型的配置工具:
- 包管理器:例如npm和yarn,用来安装和管理Node.js包
- 打包工具:用于高效地打包js文件,图片,字体等文件,常见的打包工具有WebPack,esbuild,Parcel和Vite
- 任务管理器,用于自动化执行重复性的工作流程,如Grunt和Gulp
构建工具可以帮助你:
- 将JS模块和CSS组合成打包文件,以用于生成环境
- 压缩文件以提高性能
- 使用一条命令运行单元测试
- 自动预览应用的更改
在你还不了解构建工具时你就可以使用它了!许多流行的框架和库都会用架构工具来自动化流程,例如create-react-app
和 Gatsby
使用构建工具来自动化其开发和部署过程的各个方面。
构建工具类型
让我们重点了解两种类型的构建工具:任务运行器(task runners)和打包工具(bundlers)
-
任务运行器 主要用于自动化某些开发流程,例如将 SCSS 编译为 CSS,或将 TypeScript 编译为 JavaScript。常见的 JavaScript 任务运行器包括 Grunt 和 gulp.js。
-
打包工具 负责将 JavaScript 文件及其他资源(如样式表、图片和字体)打包成合适的文件。打包工具还能移除未使用的代码和重复代码,提高下载速度。常见的打包工具包括 Webpack 、esbuild 、Parcel 和 Vite。
对于许多应用而言,使用简单的任务运行器就足够了。然而,对于需要处理大量资源的复杂应用,可能既需要自动化工具,又需要打包工具。
在后续课程中,我们将使用 Webpack 介绍不同规模应用的常见构建流程。
依赖图
打包工具需要映射资源之间的连接,以生成包含应用程序所需所有内容的输出文件。这个过程使用了一种称为依赖图(dependency graph) 的数据结构
依赖图 是一种由 有向图 组成的数据结构,用于表示不同文件之间的关系。当一个文件依赖于另一个文件时,图中会添加一条连接。
一旦所有连接都被添加,打包工具就能清楚地知道在构建过程中需要包含哪些内容。
请查看右侧的依赖图示例:
index.js
依赖于两个文件:style.css
和user.js
。style.css
还依赖于一个字体文件:font.woff
。user.js
依赖于另一个 JavaScript 文件util.js
,以及两个图片资源:banner.png
和profile.png
。
提高性能
如果没有优化,大型复杂的应用程序在浏览器中加载可能要花费很长时间。构建工具利用诸如代码分割,压缩,无效代码消除,树摇等过程来减少下载的大小
-
代码分割 是一种技术,允许你将代码拆分成多个文件或块,可以根据需要加载。
-
压缩 是一种过程,它会从代码中删除 注释 、空白符 和其他不必要的数据。代码中的引用也可以被重命名,以使最终的打包文件更小。
-
无效代码消除 旨在删除在最终应用程序中实际上没有使用的代码。
-
树摇(tree-shaking) 是一种无效代码消除技术,它会查找已包含的 模块 和 函数,以删除那些没有被使用的部分。
构建工具通常结合这些策略来帮助你简化web应用
Linting(代码检查)
学习如何使用 代码检查工具(linters) 帮助你的代码避免错误和安全漏洞
Linter 是一种用于扫描源代码的工具,它可以检测 语法错误 、有问题的代码结构 、风格不一致 和 安全漏洞 。Lint 工具能够在开发过程中 自动检测 缺失的分号或潜在的安全隐患,从而减少在测试阶段需要修复的错误数量。
常见的 Lint 工具包括:
- ESLint(适用于 JavaScript)
- JSHint(适用于 JavaScript)
- Stylelint(适用于 CSS)
为什么要使用Linter
Lint 工具提供了一系列自动检查,有助于优化软件开发流程。
-
技术问题
-
语法错误:Linter 可以在运行代码之前 自动发现并修复语法错误,这样在正式环境中遇到的 Bug 就会减少。
-
问题代码结构(代码异味):Linter 还能标记 潜在的代码结构问题 ,也称为 "代码异味"(code smells) 。
这些问题可能会影响应用程序的稳定性和性能,例如:方法过长,重复代码
-
代码风格规范:Linter 还能促使开发者 遵循统一的代码风格,提高代码的可读性和可维护性。保持一致的代码风格,可以让开发者专注于应用程序的架构和核心逻辑,而不是代码格式问题。
-
安全性:某些 Linter(如 ESLint )可以检测代码中的 潜在安全漏洞 ,帮助开发者 增强应用的安全性。
Lint 工具 vs. 构建工具
Lint 工具 和 构建工具 都可以对源码进行检查和修改,但它们属于不同类型的开发工具。
- Lint 工具 会在你编写代码时进行检查和提示。
- 构建工具(如 Webpack、Parcel)通常在代码打包、预览或部署时才会执行。
- 不过,一些构建工具 可以集成 Lint 过程,如 Webpack 和 Parcel。
浏览器兼容性和转译
介绍
你最新的网站大受欢迎,来自世界各地的用户纷纷涌入,想看看你提供了什么。然而,你开始听到一些用户的反馈------他们无法使用你的网站。网站无法在他们的浏览器上加载,控制台显示语法错误!这很奇怪,因为在你的电脑上并没有任何错误。发生了什么?
网站会将其代码发送到浏览器进行解析和执行。人们使用不同的浏览器应用程序,而每个浏览器运行的版本取决于它最近的更新时间。
随着 JavaScript 新功能的不断增加,浏览器需要更新以识别和解析这些新特性。如果浏览器没有更新,它就无法识别新的语法,并会将其视为无效的 JavaScript 代码,从而抛出错误。使用过时浏览器的用户可能会看到一个完全不同(而且很可能是损坏的)的版本的网站!
那么,我们能让网站适用于所有人,包括那些十年没更新浏览器的用户吗?我们是否应该只使用最老的 JavaScript 语法编写代码?
在本课中,我们将探讨浏览器兼容性问题,并介绍 转译(transpilation) 作为一种解决方案。
我们将学习如何使用 Babel 这一工具,自动将现代 JavaScript 代码转换成连最古老的浏览器都能理解的版本!
浏览器兼容性和现代JavaScript语法
什么JavaScript语法是最新的,什么对任何浏览器来说都可以正常使用的?我们怎么去找?
这些问题都和浏览器兼容性有关,也就是浏览器必须更新才能使用最新的 JavaScript 功能,但有些浏览器尚未更新,而一些用户也没有将浏览器升级到最新版本。当我们设计一个网站时,如果考虑到浏览器兼容性,就意味着要让网站在尽可能多的不同浏览器和浏览器版本上都能正确运行。
在考虑浏览器兼容性时,一个有用的资源是能够告诉我们哪些语言特性受哪些浏览器版本支持。
像 caniuse.com 这样的网站可以提供有用的浏览器兼容性信息。在这个网站上,你可以搜索 JavaScript 语言特性,并查看:
- 哪些浏览器版本支持这些特性
- 哪些浏览器版本不支持这些特性
- 多少互联网用户仍在使用不支持该特性的浏览器版本
通过这些信息,你可以判断自己的网站是否能覆盖你期望的用户群体。
在接下来的练习中,我们将学习如何使用 Babel 来提高网站在不同浏览器及其版本之间的兼容性。
转译
我们在 caniuse.com 上查询了网站使用的一些功能,结果发现只有 75% 的互联网用户能够看到我们的网站内容!怎么办?我们需要重写整个代码库吗?
实际上,JavaScript 的新特性往往只是让开发更方便 ,而不是新增功能,这种概念被称为 语法糖(syntactic sugar) 。我们可以使用旧语法来实现相同的功能,但通常编写起来更加麻烦。
例如,ES6 引入了 字符串插值(string interpolation) ,允许我们将变量和表达式直接嵌入到字符串中:
js
`You can make carbonara with ${pasta}, ${meat}, and a sauce made with ${sauce}.`;
但这段代码也可以用传统的字符串拼接(concatenation)方式来实现:
js
'You can make carbonara with ' +
pasta +
',' +
meat +
', and a sauce made with ' +
sauce +
'.';
为了让现代 JavaScript 语法 在旧浏览器上运行,我们需要对代码进行这样的转换。幸运的是,我们可以使用工具来自动完成这个过程!
编译(compilation) 是将代码从一种语言转换为另一种语言,而 转译(transpilation) 是指在同一种语言内 转换代码,使其符合不同的语法标准。我们可以使用 转译器(transpiler) 来将现代 JavaScript 代码转换为更兼容的版本。
在将代码发布到线上之前,我们会先对源码进行转译 ,生成一组更加兼容的输出文件 ,然后将这些文件发布到 Web 服务器上。这样,我们就可以继续使用现代 JavaScript 语法开发,而不必担心浏览器兼容性问题
Babel
你在上一个练习中看到的页面属于 Babel 工具的官方网站。Babel 是一个流行的 JavaScript 转译器(transpiler) ,可以集成到你的项目中!
Babel 配置
在上一个练习中,我们了解了 Babel 能为我们的项目做些什么。在本练习中,我们将练习如何设置 Babel。
Babel 是一个 Node.js 包,因此我们首先需要初始化 npm 项目,可以使用以下命令:
bash
npm init -y
npm init -y
是用于快速创建package.json
文件 的命令。 它等效于npm init
,但自动接受默认配置 ,避免手动输入每个选项。 npm会创建package.json
文件,自动填充默认值(如项目名称、版本、描述等)
这将创建一个 package.json
文件,为我们配置好项目环境。
接下来,我们需要安装 @babel/cli 和 @babel/preset-env 作为开发依赖(devDependencies) ,可以使用以下命令:
bash
npm install --save-dev @babel/cli @babel/preset-env
-
@babel/cli 提供了 Babel 的核心功能以及命令行接口(CLI)。
-
@babel/preset-env 是一种标准的 Babel 预设,可以帮助我们转译所有常见的 ES6 语法,而不需要手动列出每个特性。
配置 Babel
Babel 通过一个名为 .babelrc
的配置文件进行设置。我们创建.babelrc文件之后,该文件的内容非常简单:
json
{
"presets": ["@babel/preset-env"]
}
.babelrc
文件的作用是告诉 Babel 使用 @babel/preset-env 这个配置,从而将最新的 JavaScript 语法 转译成兼容旧版浏览器的代码。
定义 Babel 运行命令
接下来,我们需要定义一个构建(build)命令 ,用于运行 Babel。我们可以在 package.json
文件的 scripts
部分添加以下内容:
json
"scripts": {
"build": "babel src -d out"
}
这个命令的作用如下:
babel
:运行 Babel (由 @babel/cli 提供)。src
:指定要转译的源代码所在目录。-d out
:指定 Babel 处理后的代码存放到out
目录中。
运行Babel
现在,我们可以使用下面的命令来执行 Babel 转译:
bash
npm run build
这样,Babel 就会将 src
目录中的代码转译并存储到 out
目录中,使其兼容旧版浏览器。
针对不同的浏览器
除了提供快速配置Babel的方式外,babel-preset-env 还允许我们通过一个名为 .browserslistrc 的文件来指定需要支持的浏览器列表。
在 .browserslistrc 文件中,我们可以使用多种方式来定义目标浏览器列表。例如,一个不错的默认配置,可以覆盖大多数开发者期望用户使用的浏览器:
defaults
当然,我们也可以自定义 这个列表。例如,如果我们想确保我们的项目支持最近两个版本的 Internet Explorer,可以这样写:
perl
last 2 Explorer versions
或者,如果你希望确保你的应用能覆盖 99.5% 的互联网用户,可以这样写:
erlang
cover 99.5%
browserslist 官方文档提供了更多配置 .browserslistrc 的语法和示例,可以帮助我们更精确地定义目标浏览器。 定义 .browserslistrc 之后,可以使用以下命令查看当前配置支持的浏览器列表:
npx browserslist
npx和npm的区别
npx
是 Node.js 生态系统中的一个工具,它和npm
(Node Package Manager)类似,但有一些不同的用途。 当你在项目中安装了一些 npm 包(如browserslist
、babel
),但它们没有全局安装 ,你仍然可以使用npx
来运行它们,而不需要指定完整路径。 例如,在一个安装了browserslist
的项目中,你可以运行: npx browserslist
npm和npx的区别:
npm:
-
用于安装包,如npm install
-
需要全局或本地安装包才能使用
-
适用于管理依赖
-
可以用来运行脚本,如
npm run build
:运行package.json
里scripts
里定义的build
命令
npx:
-
用于运行 npm 包,而不一定要安装
-
可以直接运行,不用安装
-
适用于临时运行或执行一次性命令
通过webpack构建应用
是时候来练习使用构建工具了,我们将用最流行的构建工具之一------webpack来打包以下内容:
-
JavaScript 文件
-
样式表(stylesheets)
-
图片(images)
-
字体(fonts)
-
文本文件(text files)