介绍完整的工具链

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

先决条件 熟悉核心HTMLCSSJavaScript语言。
目标 通过完成一个完整的工具链案例研究来巩固我们迄今为止所学到的知识。

工具和使用它们的组合方式实际上是无限的,您在本篇文章和下一篇文章中看到的仅仅是一种使用所介绍工具进行项目的方法。

注意:还值得重复的是,并非所有这些工具都需要在命令行上运行。当今许多代码编辑器(例如 VS Code)通过插件对许多工具提供了集成支持。

介绍我们的案例研究

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

工具链中使用的工具

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

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

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

工具链及其固有的复杂性

与任何链条一样,工具链中包含的链接越多,它就越复杂,也可能越脆弱——例如,它可能更难配置,也更容易出现故障。相反,链接越少,工具链的弹性可能就越大。

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

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

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

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

检查先决条件

如果您一直在关注前几章,那么您应该已经拥有大部分软件。以下是您在继续执行实际设置步骤之前应该拥有的内容。这些步骤只需执行一次,您无需在以后的项目中重复执行。

创建 GitHub 帐户

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

如果您还没有帐户,请点击主页上的注册链接,注册GitHub,并按照说明操作。

安装 git

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

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

对于某些人来说,这可能很明显,但值得重复的是:Git 与 GitHub 不一样。Git 是版本控制工具,而GitHub是 git 存储库的在线存储库(以及一些用于处理它们的实用工具)。请注意,虽然我们本章使用的是 GitHub,但还有其他几种选择,包括GitLabBitbucket,您甚至可以托管自己的 git 存储库。

在您的项目中使用版本控制并将其包含为工具链的一部分将有助于管理您的代码演变。它提供了一种在您进行时“提交”工作块的方法,以及诸如“X 新功能实现”或“由于 Y 更改,Bug 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。
  • 代码风格检查工具——用于检查我们的代码。

库安装工具

您已经完成了此操作,但为了便于参考,以下是(在 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 hook”来测试在提交之前代码是否已格式化。
  • 使用代码编辑器插件在每次保存文件时运行 Prettier 命令。

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

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

代码 linting 工具

Linting 有助于提高代码质量,但也是在开发过程中尽早捕获潜在错误的一种方法。它是良好工具链的关键组成部分,许多开发项目默认情况下会包含它。

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

JavaScript linting 的首选工具是ESLint。它是一个非常强大且通用的工具,但配置正确可能很棘手,您很容易花费很多时间尝试获得恰到好处的配置!

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

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

注意:esling@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 关于浏览器全局变量的存在(用于 linting 规则,例如用于检查不存在的变量的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配置的一行添加相比,我们对eslint-plugin-react-hooks的配置有点笨拙。这是因为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 更接近网络,学习曲线更低。 Vite 默认支持 PostCSS,因此如果您想编译任何功能,只需要配置 PostCSS即可。查看cssdb,了解支持哪些功能。

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

虽然我们工具链的这一阶段可能非常痛苦,因为我们选择了一种故意尝试减少配置和复杂性的工具,但在开发阶段我们实际上不需要做更多的事情。模块已正确导入,嵌套 CSS 已正确转换为“常规 CSS”,并且我们的开发不受构建过程的阻碍。

现在我们的软件已经准备好编写了!

编写源代码

现在我们已经设置好了完整的开发工具链,通常是时候开始编写真正的代码了——这部分是你应该投入最多时间的部分。不过,为了我们的目的,我们将直接复制一些现有的源代码,并假装是我们自己写的。我们不会教你它们是如何工作的,因为这不是本章的重点。它们只是为了运行这些工具,教你它们是如何工作的。

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

The GitHub example repo

现在将项目src目录的内容复制出来,并用它替换您当前的src目录。您不必担心其他文件。

还要安装源代码使用的一些依赖项

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

我们已经将项目文件准备就绪。现在我们只需要做这些了!

运行转换

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

  1. 要在后台启动 Vite,请转到您的终端并运行以下命令(使用我们之前定义的自定义脚本)
    bash
    npm run dev
    
    您应该看到类似于这样的输出(一旦依赖项已安装)
    > [email protected] dev
    > vite
    
    Re-optimizing dependencies because lockfile has changed
    
      VITE v5.2.13  ready in 157 ms
    
      ➜  Local:   https://127.0.0.1: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 将是下一章的目标!