介绍完整的工具链

在本系列文章的最后几篇中,我们将通过指导您构建一个示例案例研究工具链来巩固您的工具知识。我们将从设置合理的开发环境和部署转换工具,直到实际部署您的应用程序。在本文中,我们将介绍案例研究、设置开发环境并设置代码转换工具。

预备知识 熟悉核心 HTMLCSSJavaScript 语言。
目标 通过完整的工具链案例研究来巩固我们目前所学到的知识。

工具的组合和使用方式是无限的,您在本文和下一篇文章中看到的只是所介绍的工具可用于项目的一种方式。

注意: 值得重申的是,并非所有这些工具都需要在命令行上运行。如今的许多代码编辑器(例如 VS Code)都通过插件支持大量工具。

介绍我们的案例研究

我们将在本文中创建的工具链将用于构建和部署一个微型网站,该网站显示有关 mdn/content 存储库的数据,其数据来源于 GitHub API

我们工具链中使用的工具

在本文中,我们将使用以下工具和功能

  • JSX,一组与 React 相关的语法扩展,允许您在 JavaScript 中定义组件结构。您无需了解 React 即可遵循本教程,但我们将其包含在内,以便让您了解非原生 Web 语言如何集成到工具链中。
  • 最新的内置 JavaScript 功能(撰写本文时),例如 import
  • 有用的开发工具,例如用于格式化的 Prettier 和用于 Linting 的 ESLint
  • PostCSS 提供 CSS 嵌套功能。
  • Vite 用于构建和缩小代码,并自动为我们编写大量配置文件内容。
  • GitHub 用于管理我们的源代码控制,并最终部署我们的网站(使用 GitHub Pages)。

您可能不熟悉上述所有功能和工具或它们的作用,但请不要惊慌——我们将在这篇文章中逐一解释每个部分。

工具链及其固有的复杂性

与任何链条一样,工具链中的链接越多,它就越复杂,也越脆弱——例如,它可能更复杂,更容易损坏。反之,链接越少,工具链就越有弹性。

所有 Web 项目都将有所不同,您需要考虑工具链的哪些部分是必要的,并仔细考虑每个部分。

最小的工具链是没有链接的工具链。您将手动编写 HTML,使用“原生 JavaScript”(这意味着没有框架或中间语言),并手动将所有内容上传到服务器进行托管。

然而,更复杂的软件需求可能会受益于使用工具来帮助简化开发过程。此外,您应该在部署到生产服务器之前进行测试,以确保您的软件按预期工作——这听起来已经是一个必要的工具链了。

对于我们的示例项目,我们将使用专门设计的工具链来辅助我们的软件开发并支持软件设计阶段做出的技术选择。但是,我们将避免任何多余的工具,旨在将复杂性降到最低。

检查先决条件

如果您一直遵循前面的章节,那么您应该已经拥有大部分软件。在进行实际设置步骤之前,您应该具备以下条件。它们只需要执行一次,将来不需要为其他项目重复。

创建 GitHub 帐户

除了我们将要安装的构成工具链的工具之外,如果您希望完成本教程,还需要创建一个 GitHub 帐户。但是,您仍然可以在没有它的情况下进行本地开发。如前所述,GitHub 是一种源代码存储库服务,它增加了诸如问题跟踪、关注项目发布等社区功能。在下一章中,我们将推送到 GitHub 代码存储库,这将导致级联效应,(应该)将所有软件部署到 Web 上的一个家。

如果您还没有帐户,请单击主页上的 Sign Up 链接注册 GitHub,然后按照说明进行操作。

安装 Git

我们将安装另一个软件 Git,以帮助进行版本控制。

您可能以前听说过“Git”。Git 是目前开发人员最流行的源代码版本控制工具——版本控制提供了许多优势,例如在远程位置备份工作的方式,以及在同一个项目上以团队形式工作而无需担心覆盖彼此代码的机制。

对某些人来说可能很明显,但值得重申:Git 与 GitHub 不是一回事。Git 是版本控制工具,而 GitHub 是 Git 仓库的在线商店(以及许多用于处理它们的有用工具)。请注意,尽管我们在本章中使用 GitHub,但还有其他几种替代方案,包括 GitLabBitbucket,您甚至可以托管自己的 Git 仓库。

在您的项目中使用版本控制并将其作为工具链的一部分,将有助于管理代码的演变。它提供了一种在您进行过程中“提交”工作块的方式,并附有诸如“实现了 X 新功能”或“由于 Y 更改,错误 Z 现已修复”之类的注释。

版本控制还可以让您将项目代码“分支”出来,创建一个单独的版本,并在其上尝试新功能,而这些更改不会影响您的原始代码。

最后,如果某个地方出现了错误并且您难以修复它,它可以帮助您撤消更改或将代码恢复到“正常工作”的时间——这是所有开发人员都需要偶尔做的事情!

Git 可以通过 git-scm 网站下载和安装——下载适用于您系统的相关安装程序,运行它,然后按照屏幕上的提示操作。目前您只需要做这些。

您可以通过多种不同的方式与 Git 交互,从使用命令行发出命令,到使用 Git GUI 应用程序通过按钮发出相同的命令,甚至可以直接在代码编辑器中进行,如下面的 Visual Studio Code 示例所示

Git integration shown in VS Code

现有项目

我们将在上一章中已经开始的项目基础上进行构建,因此请务必首先按照 包管理 中的说明设置项目。回顾一下,您应该拥有

  • 已安装 Node.js 和 npm。
  • 一个名为 npm-experiment(或其他名称)的新项目。
  • Vite 已作为开发依赖项安装。
  • plotly.js-dist-min 包已作为依赖项安装。
  • package.json 中定义了一些自定义脚本。
  • index.htmlsrc/main.jsx 文件已创建。

正如我们在 第 1 章 中讨论的那样,工具链将分为以下几个阶段

  • 开发环境:运行代码最基本的工具。此部分已在上一章中设置。
  • 安全网:使软件开发体验稳定高效。我们也可以称之为我们的开发环境。
  • 转换:允许我们在开发过程中使用语言(例如 JavaScript)的最新功能或完全不同的语言(例如 JSX 或 TypeScript)的工具,然后转换我们的代码,以便生产版本仍然可以在各种浏览器(现代和旧版)上运行。
  • 开发后:在您完成大部分开发后投入使用的工具,以确保您的软件能够发布到网络并持续运行。在这个案例研究中,我们将研究如何向代码添加测试,并使用 GitHub Pages 部署您的应用程序,以便所有网络用户都可以看到它。

让我们开始着手这些,从我们的开发环境开始。我们将遵循与真实项目设置相同的步骤,因此将来,如果您要设置新项目,可以参考本章并再次遵循这些步骤。

创建开发环境

工具链的这一部分有时被视为延迟实际工作,而且很容易陷入工具的“兔子洞”,花费大量时间试图让环境“恰到好处”。

但您可以将其视为设置您的物理工作环境。椅子需要舒适,并设置在有助于您姿势的良好位置。您需要电源、Wi-Fi 和 USB 端口!可能还有重要的装饰或音乐有助于您的精神状态——这些对于尽力而为至关重要,而且如果做得好,它们也应该只需要设置一次。

同样,如果做得好,您的开发环境只需要设置一次,并且可以在许多未来的项目中重复使用。您可能希望定期审阅工具链的这一部分,并考虑是否应该引入任何升级或更改,但这不应该太频繁地需要。

您的工具链将取决于您自己的需求,但对于这个相当完整的工具链示例,将预先安装/初始化的工具将是

  • 库安装工具 — 用于添加依赖项。
  • 代码版本控制。
  • 代码整理工具 — 用于整理 JavaScript、CSS 和 HTML。
  • 代码 Linting 工具 — 用于 Linting 我们的代码。

库安装工具

您已经完成了此操作,但为了方便参考,以下是在 npm-experiment 目录的根目录中运行的命令,用于初始化 npm 包并安装必要的依赖项

bash
npm init
npm install --save-dev vite
npm install plotly.js-dist-min

代码版本控制

输入以下命令以启动 Git 的源代码控制功能在目录中工作

bash
git init

默认情况下,Git 跟踪所有文件的更改。但是,有些生成的文件我们不需要跟踪,因为它们不是我们编写的代码,并且可以随时重新生成。我们可以通过在项目目录的根目录中创建一个 .gitignore 文件来告诉 Git 忽略这些文件。将以下内容添加到文件中

node_modules
dist

代码整理工具

我们将使用 Prettier(我们首次在第 2 章中遇到)来整理此项目中的代码。我们将在此项目中再次安装 Prettier。使用以下命令安装它

bash
npm install --save-dev prettier

再次注意,我们使用 --save-dev 将其添加为开发依赖项,因为我们只在开发期间使用它。

像许多最近制作的工具一样,Prettier 带有“合理的默认值”。这意味着您无需配置任何东西即可使用 Prettier(如果您对 默认值 感到满意)。这让您可以专注于重要的事情:创意工作。为了演示,我们将添加一个配置文件。在 npm-experiment 目录的根目录下创建一个名为 .prettierrc.json 的文件。添加以下内容

json
{
  "bracketSameLine": true
}

通过此设置,Prettier 会将多行 HTML(HTML、JSX、Vue、Angular)开始标签的 > 打印在最后一行的末尾,而不是单独放在下一行。这是 MDN 自己使用的格式。您可以在其文档中找到有关 配置 Prettier 的更多信息。

默认情况下,Prettier 会格式化您指定的所有文件。但是,我们同样不需要格式化生成的文件,或者可能有一些我们不想触碰的旧代码。我们可以通过在项目目录的根目录下创建一个 .prettierignore 文件来告诉 Prettier 始终忽略这些文件。将以下内容添加到文件中

node_modules
dist

它的内容与 .gitignore 相同,但在真实项目中,您可能希望 Prettier 忽略的文件与 Git 忽略的文件不同。

现在 Prettier 已安装并配置,可以在命令行上运行和整理您的代码,例如

bash
npx prettier --write ./index.html

注意: 在上面的命令中,我们使用带有 --write 标志的 Prettier。Prettier 将其理解为“如果我的代码格式有任何问题,请修复它们,然后保存我的文件”。这对于我们的开发过程来说很好,但我们也可以在没有标志的情况下使用 prettier,它只会检查文件。检查文件(而不保存它)对于发布前运行的检查等目的很有用——即“不要发布任何未正确格式化的代码。”

您还可以将 ./index.html 替换为任何其他文件或文件夹以对其进行格式化。例如,. 将格式化当前目录中的所有内容。如果您忘记了语法,您也可以将其作为自定义脚本添加到您的 package.json 中

json
{
  "scripts": {
    // …
    "format": "prettier --write ."
  }
}

现在您可以运行以下命令来格式化目录

bash
npm run format

每次我们更改某些内容时都运行该命令仍然很麻烦,并且有几种方法可以自动化此过程

  • 使用特殊的“git 钩子”在提交前测试代码是否已格式化。
  • 使用代码编辑器插件在每次保存文件时运行 Prettier 命令。

注意: 什么是 Git 钩子?Git(不是 GitHub)提供了一个系统,允许我们将前置和后置操作附加到我们使用 Git 执行的任务(例如提交代码)。虽然 Git 钩子可能有点过于复杂(在本文作者看来),但一旦它们就位,它们就会非常强大。如果您有兴趣使用钩子,Husky 是使用钩子的一个大大简化的途径。

对于 VS Code,一个有用的扩展是 Esben Petersen 的 Prettier Code Formatter,它允许 VS Code 在保存时自动格式化代码。这意味着我们正在处理的项目中的任何文件都会被很好地格式化,包括 HTML、CSS、JavaScript、JSON、Markdown 等。编辑器只需要启用“保存时格式化”。

代码 Linting 工具

Linting 有助于代码质量,也是在开发早期发现潜在错误的一种方式。它是良好工具链的关键组成部分,也是许多开发项目默认会包含的工具。

Web 开发 Linting 工具主要用于 JavaScript(尽管也有一些适用于 HTML 和 CSS)。这是有道理的:如果使用了未知的 HTML 元素或无效的 CSS 属性,由于这两种语言的弹性特性,不太可能出现问题。JavaScript 要脆弱得多——例如,错误地调用不存在的函数会导致您的 JavaScript 崩溃;因此 Linting JavaScript 非常重要,尤其是对于大型项目。

用于 JavaScript Linting 的首选工具是 ESLint。它是一个极其强大和通用的工具,但配置起来可能很棘手,您很容易花费数小时试图获得“恰到好处”的配置!

ESLint 通过 npm 安装,因此根据第 2 章中的讨论,您可以选择在本地或全局安装此工具,但强烈建议进行本地安装,因为您无论如何都需要为每个项目提供一个配置文件。记住要运行的命令

bash
npm install --save-dev eslint@8 @eslint/js globals

注意: eslint@8 安装 ESLint 的版本 8,而最新版本是 v9。这是因为我们稍后将使用的 eslint-plugin-react 尚不支持 v9

@eslint/js 包提供了预定义的 ESLint 配置,而 globals 包提供了每个环境中已知全局名称的列表。我们将在稍后的配置中使用它们。开箱即用,如果您使用 npx eslint 运行 ESLint,它会抱怨找不到配置文件

Oops! Something went wrong! :(

ESLint: 8.57.0

ESLint couldn't find a configuration file. To set up a configuration file for this project, please run:

...

这是一个最小的示例,它在项目根目录下的 eslint.config.js 文件中有效

js
import js from "@eslint/js";
import globals from "globals";

export default [
  js.configs.recommended,
  {
    ignores: ["node_modules", "dist"],
  },
  {
    files: ["**/*.{js,jsx}"],
    languageOptions: {
      globals: {
        ...globals.browser,
      },
    },
  },
];

上述 ESLint 配置

  • 启用“推荐”的 ESLint 设置
  • 告诉 ESLint 忽略生成的文件,就像我们对其他工具所做的那样
  • 告诉 ESLint 在 Linting 中包含 .js.jsx 文件
  • 告诉 ESLint 浏览器全局变量的存在(Lint 规则(例如 no-undef)用于检查不存在的变量)。

ESLint 解析器默认不理解 JSX,其推荐规则也不处理 React 特定的语义。因此,我们将添加更多配置以使其正确支持 JSX 和 React。首先,安装 eslint-plugin-reacteslint-plugin-react-hooks,它们提供用于编写正确和地道的 React 的规则

bash
npm install --save-dev eslint-plugin-react eslint-plugin-react-hooks

然后,更新 ESLint 配置文件以包含这些插件的推荐配置,它既加载推荐规则又为 JSX 设置解析器选项

js
import js from "@eslint/js";
import globals from "globals";
import reactRecommended from "eslint-plugin-react/configs/recommended.js";
import reactJSXRuntime from "eslint-plugin-react/configs/jsx-runtime.js";
import reactHooksPlugin from "eslint-plugin-react-hooks";

export default [
  js.configs.recommended,
  {
    ignores: ["node_modules", "dist"],
  },
  {
    files: ["**/*.{js,jsx}"],
    languageOptions: {
      globals: {
        ...globals.browser,
      },
    },
    settings: {
      react: {
        version: "detect",
      },
    },
  },
  reactRecommended,
  reactJSXRuntime,
  {
    plugins: {
      "react-hooks": reactHooksPlugin,
    },
    rules: reactHooksPlugin.configs.recommended.rules,
  },
];

注意: 我们的 eslint-plugin-react-hooks 配置与 eslint-plugin-react 配置的一行添加相比有点尴尬。这是因为 eslint-plugin-react-hooks 尚不支持新的 ESLint 配置格式。有关更多信息,请参阅 facebook/react#28313

有一份完整的 ESLint 规则列表,您可以随意调整和配置,许多公司和团队都发布了他们自己的 ESLint 配置,这有时可能有助于获取灵感或选择一个您认为符合您自己标准的配置。不过,请注意:ESLint 配置是一个非常深的兔子洞!

为简单起见,在本章中,我们不会探讨 ESLint 的所有功能,因为此配置适用于我们特定的项目及其要求。但是,请记住,如果您想改进和强制执行有关代码外观(或验证)的规则,很可能可以通过正确的 ESLint 配置来完成。

与其他工具一样,ESLint 的代码编辑器集成支持通常很好,并且可能更有用,因为它可以在出现问题时为我们提供实时反馈

ESLint error integration shown in VS Code

至此,我们的开发环境设置已完成。现在,我们(几乎)准备好编码了。

构建和转换工具

JavaScript 转换

对于这个项目,如上所述,将使用 React,这也意味着在源代码中将使用 JSX。项目还将使用最新的 JavaScript 功能。一个直接的问题是,没有浏览器原生支持 JSX;它是一种中间语言,旨在编译成生产代码中浏览器能够理解的语言。如果浏览器尝试运行源代码 JavaScript,它会立即报错;项目需要一个构建工具来将源代码转换为浏览器可以毫无问题地使用的内容。

有多种转换工具可供选择,虽然 Babel 是一个特别流行的工具,但在 Vite 中,我们将使用一个集成插件:@vitejs/plugin-react。使用以下命令安装它

bash
npm install --save-dev @vitejs/plugin-react

我们还没有 Vite 配置!在项目目录的根目录下添加一个 vite.config.js

js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  base: "/npm-experiment/",
});

有关如何配置 Vite 的更多信息,请阅读 Vite 文档。因为我们的网站部署在 GitHub Pages 上,它将托管在 https://your-username.github.io/your-repo-name,所以您应该根据您的 GitHub 存储库名称设置 base 选项——但我们可以在稍后进行 部署 时随时调整它。

CSS 转换

我们的 CSS 也可能使用浏览器不理解的语法。例如,您可能使用了只在最近几个浏览器版本中才实现的语法,这意味着旧浏览器将无法正常显示并显示损坏的样式。我们可以使用工具将 CSS 转换为我们目标的所有浏览器都能理解的格式。

PostCSS 是一款 CSS 后处理器工具。与 Sass 等构建工具相比,PostCSS 旨在编写 标准 CSS(即可能有一天会进入浏览器的 CSS 语法),而 Sass 本身是一种自定义语言,可编译为 CSS。PostCSS 更接近 Web,学习曲线也更低。Vite 默认支持 PostCSS,因此您只需要配置 PostCSS 即可编译任何功能。查看 cssdb 了解支持哪些功能。

出于我们的目的,我们将演示另一个 CSS 转换:CSS 模块。它是实现 CSS 模块化 的方法之一。请记住,CSS 选择器都是全局的,所以如果您有一个像 .button 这样的类名,所有带有类名 button 的元素都将以相同的方式进行样式设置。这通常会导致命名冲突——想象一下您所有的 JavaScript 变量都在全局作用域中定义!CSS 模块通过使类名对于使用它们的页面是唯一的来解决这个问题。要了解它是如何工作的,在您下载源代码后,您可以查看我们如何使用 .module.css 文件,并阅读 CSS 模块文档

尽管我们工具链的这个阶段可能会相当痛苦,但由于我们选择了一个故意尝试减少配置和复杂性的工具,所以在开发阶段我们真的不需要做更多的事情。模块被正确导入,嵌套的 CSS 被正确转换为“常规 CSS”,我们的开发不会受到构建过程的阻碍。

现在我们的软件可以编写了!

编写源代码

现在我们已经建立了完整的开发工具链,通常是时候开始编写真正的代码了——您应该投入最多时间的部分。但出于我们的目的,我们只是复制一些现有的源代码,假装是我们编写的。我们不会教您它们是如何工作的,因为这不是本章的重点。它们只是为了在其上运行工具,以教您它们是如何工作的。

要获取代码文件,请访问 https://github.com/mdn/client-toolchain-example 并将此存储库的内容下载并解压缩到您本地驱动器的某个位置。您可以通过选择 Clone or download > Download ZIP 来下载整个项目作为 zip 文件。

The GitHub example repo

现在复制项目 src 目录的内容,并用它替换您当前的 src 目录。您无需担心其他文件。

另外安装源代码使用的一些依赖项

bash
npm install react react-dom @tanstack/react-query

我们的项目文件已经就位。目前我们只需要做这些!

运行转换

要开始使用我们的项目,我们将在命令行上运行 Vite 服务器。在默认模式下,它将监视代码中的更改并刷新服务器。这很好,因为我们不必在代码和命令行之间来回切换。

  1. 要在后台启动 Vite,请转到您的终端并运行以下命令(使用我们之前定义的自定义脚本)

    bash
    npm run dev
    

    您应该会看到这样的输出(一旦依赖项安装完毕)

    > client-toolchain-example@1.0.0 dev
    > vite
    
    Re-optimizing dependencies because lockfile has changed
    
      VITE v5.2.13  ready in 157 ms
    
      ➜  Local:   https://:5173/
      ➜  Network: use --host to expose
      ➜  press h + enter to show help
    

    服务器现在正在打印的 URL 上运行(在本例中为 localhost:5173)。

  2. 在浏览器中访问此 URL,您将看到示例应用程序正在运行!

现在我们可以进行一些更改并实时查看它们的效果。

  1. 在您喜欢的文本编辑器中加载文件 src/App.jsx
  2. 将所有出现的 mdn/content 替换为您最喜欢的 GitHub 存储库,例如 facebook/react
  3. 保存文件,然后立即返回浏览器中运行的应用程序。您会注意到浏览器已自动刷新,并且图表已更改!

您还可以尝试使用 ESLint 和 Prettier——尝试故意从您的一个文件中删除大量空格,然后运行 Prettier 来清理它,或者在您的一个 JavaScript 文件中引入语法错误,然后查看运行 eslint 命令或在编辑器中 ESLint 会给您带来什么错误。

总结

在本章中,我们已经取得了很大的进步,建立了一个相当不错的本地开发环境来创建应用程序。

在 Web 软件开发的这个阶段,您通常会为要构建的软件精心编写代码。由于本模块是关于学习 Web 开发的工具,而不是 Web 开发代码本身,因此我们不会教您任何实际的编码——您将在 MDN 的其余部分找到这些信息!

相反,我们为您编写了一个示例项目,供您使用您的工具。我们建议您使用我们的示例代码完成本章的其余部分,然后您可以尝试将 src 目录的内容更改为您自己的项目,并将其发布到 GitHub Pages 上!实际上,部署到 GitHub Pages 将是下一章的最终目标!