部署我们的应用程序

在本系列的最后一篇文章中,我们将使用上一篇文章中构建的示例工具链并添加更多内容,以便我们可以部署示例应用程序。我们将代码推送到 GitHub,使用 GitHub Pages 部署,甚至向您展示如何将简单的测试添加到该过程中。

先决条件 熟悉核心 HTMLCSSJavaScript 语言。
目标 完成整个工具链案例研究,重点关注应用程序的部署。

开发后

在这个项目的生命周期部分中,可能存在大量需要解决的问题。因此,创建能够以尽可能少的手动干预处理这些问题的工具链非常重要。

以下是一些需要考虑的特定于此项目的因素:

  • 生成生产版本:确保文件已压缩、分块、应用了树状摇动,以及版本已“缓存失效”。
  • 运行测试:这些测试可以从“代码是否正确格式化?”到“这个东西是否按预期工作?”,并确保失败的测试阻止部署。
  • 将更新后的代码实际部署到实时 URL:或者可能是一个用于预发布的暂存 URL,以便先进行审查。

注意:缓存失效是我们之前在模块中没有遇到的新术语。这是一种打破浏览器自身的缓存机制的策略,它迫使浏览器下载代码的新副本。Vite(以及许多其他工具)将生成每个新版本特有的文件名。这个唯一的文件名会“失效”浏览器的缓存,从而确保浏览器每次更新部署的代码时都会下载最新的代码。

以上任务还会进一步细分;请注意,大多数 Web 开发团队都会对开发后阶段的至少一部分使用自己的术语和流程。

对于这个项目,我们将使用 GitHub Pages 的免费静态托管服务来托管我们的项目。它不仅在互联网上为我们的网站提供服务,还为我们的网站提供了 URL。它很棒——许多 MDN 示例网站都托管在 GitHub Pages 上。

部署到托管通常是在项目生命周期的最后阶段进行,但随着 GitHub Pages 等服务的出现,降低了部署成本(从财务角度以及实际部署所需的时间来看),可以在开发过程中进行部署,以共享正在进行的工作或出于其他目的进行预发布。

GitHub 提供了一个流畅的工作流程,将新代码转换为实时网站

  • 您将代码推送到 GitHub。
  • 您定义了一个 GitHub Action,它会在主分支出现新推送时触发,该 Action 会构建代码并将其放在特定位置。
  • 然后 GitHub Pages 会在特定 URL 上提供该代码。

正是这些相互关联的服务,我们鼓励您在选择自己的构建工具链时寻找。我们可以提交代码并推送到 GitHub,更新后的代码会自动触发整个构建过程。如果一切顺利,我们就会自动获得一个实时更改的部署。我们唯一需要执行的操作是最初的“推送”。

但是,我们必须设置这些步骤,现在我们将对此进行介绍。

构建过程

同样,由于我们在开发中使用的是 Vite,因此构建选项非常容易添加。正如我们之前所看到的,我们已经有一个自定义脚本 npm run build,它可以让 Vite 构建所有准备投入生产的内容,而不是仅仅为了开发和测试目的而运行它。这包括对代码进行 压缩树状摇动,以及对文件名进行缓存失效。

最佳实践是始终在项目中定义一个 build 脚本,这样我们就可以依靠 npm run build 来始终执行完整的构建步骤,而无需记住每个项目的特定构建命令参数。

新创建的生产代码被放置在一个名为 dist 的新目录中,该目录包含运行网站所需的所有文件,您可以将其上传到服务器。

但是,手动执行此步骤并不是我们的最终目标——我们希望构建能够自动进行,并且 dist 目录的结果能够实时部署到我们的网站上。

将更改提交到 GitHub

本节将帮助您完成将代码存储在 Git 存储库中的过程,但这远远不是 Git 教程。有很多优秀的教程和书籍可用,我们的 Git 和 GitHub 页面是一个不错的起点。

我们之前已经将工作目录初始化为 Git 工作目录。验证这一点的一个快速方法是运行以下命令

bash
git status

您应该会收到有关哪些文件正在跟踪、哪些文件已暂存等的状况报告——所有这些都是 Git 语法的一部分。如果您收到错误 fatal: not a git repository,则工作目录不是 Git 工作目录,您需要使用 git init 初始化 Git。

现在,我们面前有三个任务:

  • 将我们所做的任何更改添加到暂存区(Git 将从该暂存区提交文件的一个特殊名称)。
  • 将更改提交到存储库。
  • 将更改推送到 GitHub。
  1. 要添加更改,请运行以下命令
    bash
    git add .
    
    请注意结尾处的句号,它表示“此目录中的所有内容”。git add . 命令有点像大锤——它会一次性添加您所做的所有本地更改。如果您希望更精细地控制要添加的内容,请使用 git add -p 进行交互式操作,或者使用 git add path/to/file 添加单个文件。
  2. 现在所有代码都已暂存,我们可以提交;运行以下命令
    bash
    git commit -m 'committing initial code'
    

    注意:虽然您可以在提交消息中随意写任何内容,但网络上有一些关于优秀提交消息的有用提示。保持简短、简洁和描述性,以便它们清楚地描述更改的作用。

  3. 最后,代码需要推送到您托管在 GitHub 上的存储库中。我们现在就来做。在 GitHub 上,访问 https://github.com/new,并创建您自己的存储库来托管此代码。
  4. 为您的存储库起一个简短、易记的名称,其中不要包含空格(使用连字符分隔单词),并添加一个描述,然后单击页面底部的“创建存储库”。您现在应该拥有一个指向您的新 GitHub 存储库的“远程”URL。 GitHub 屏幕截图显示您可以用来将代码部署到 GitHub 存储库的远程 URL
  5. 在我们将代码推送到该位置之前,需要将此远程位置添加到我们的本地 Git 存储库中,否则它将无法找到它。您需要运行一个具有以下结构的命令(现在使用提供的 HTTPS 选项——特别是如果您是 GitHub 的新手——而不是 SSH 选项)
    bash
    git remote add origin https://github.com/your-name/repo-name.git
    
    因此,如果您的远程 URL 是 https://github.com/remy/super-website.git,如上图所示,您的命令将是
    bash
    git remote add origin https://github.com/remy/super-website.git
    
    将 URL 更改为您的存储库,并立即运行它。

    注意:在您选择存储库名称后,请确保 vite.config.js 中的 base 选项反映此名称,如 上一章 中所述。否则,JavaScript 和 CSS 资产将无法正确链接。

  6. 现在,我们准备将代码推送到 GitHub;现在运行以下命令
    bash
    git push origin main
    
    此时,系统会提示您输入用户名和密码,然后 Git 才会允许进行推送。这是因为我们使用了 HTTPS 选项而不是 SSH 选项,如之前的屏幕截图所示。为此,您需要您的 GitHub 用户名,以及——如果您没有启用双重身份验证 (2FA)——您的 GitHub 密码。我们始终建议您尽可能使用 2FA,但请记住,如果您使用 2FA,您还需要使用“个人访问令牌”。GitHub 帮助页面有一个 关于如何获取令牌的出色且简单的演练

注意:如果您有兴趣使用 SSH 选项,从而避免每次推送到 GitHub 时都输入用户名和密码,本教程将引导您完成操作

此最终命令指示 Git 将代码推送到我们称为 origin 的“远程”位置(即托管在 github.com 上的存储库——我们可以随意命名它)并使用 main 分支。我们还没有遇到分支,但“main”分支是我们的工作默认位置,也是 Git 开始的地方。当我们定义触发构建网站的 Action 时,我们还将让它监视“main”分支上的更改。

注意:在 2020 年 10 月之前,GitHub 的默认分支是 master,出于各种社会原因,它已切换到 main。您应该知道,此较旧的默认分支可能会出现在您遇到的各种项目中,但我们建议您在自己的项目中使用 main

因此,我们的项目已提交到 Git 并推送到 GitHub 存储库中,工具链中的下一步是定义一个构建 Action,以便我们的项目可以实时部署到网络上!

使用 GitHub Actions 进行部署

GitHub Actions 与 ESLint 配置一样,也是另一个需要深入研究的深奥话题。第一次尝试很难做到正确,但对于诸如“构建静态网站并将其部署到 GitHub Pages”之类的常见任务,有很多示例可以复制和粘贴。您可以按照 使用自定义 GitHub Actions 工作流程发布 中的说明进行操作。您可以查看 我们的 GitHub Action 文件 以获取一个工作示例。(文件名称无关紧要。)

将此文件提交到主分支后,您应该会在提交标题旁边看到一个小绿色的对勾

GitHub screenshot showing a green tick next to a commit title

如果看到一个黄色圆点,则表示 Action 正在运行;如果看到一个红色的叉号,则表示 Action 失败。单击图标,您就可以看到自己的构建 Action(在本例中名为“Deploy build”)的状态和日志。

等待几分钟后,您就可以访问您的 GitHub Pages URL,在网络上查看您的实时网站。该链接类似于 https://<your-name>.github.io/<repo-name>。对于我们的示例,该链接位于 https://mdn.github.io/client-toolchain-example/

现在,我们来介绍工具链中的最后一个环节:一个测试,以确保我们的代码正常工作。

测试

测试本身是一个庞大的主题,即使是在前端开发领域也是如此。我将向您展示如何在项目中添加一个初始测试以及如何使用该测试来阻止或允许项目部署。

在进行测试时,有很多方法可以解决问题:

  • 端到端测试,它涉及您的访问者点击某个东西,然后发生其他事情。
  • 集成测试,它基本上是说“当代码块连接到另一个代码块时,它是否仍然有效?”
  • 单元测试,对功能的细小部分进行测试,以查看它们是否按预期执行。
  • 还有很多其他类型。此外,请查看我们的 跨浏览器测试模块,其中包含大量有用的测试信息。

请记住,测试不仅限于 JavaScript;可以针对渲染后的 DOM、用户交互、CSS 甚至页面外观运行测试。

但是,在这个项目中,我们将创建一个小的测试来检查 GitHub API 数据是否处于正确的格式。如果不是,测试将失败并阻止项目上线。除此之外的其他任何事情都超出了本模块的范围——测试是一个巨大的主题,确实需要单独的模块来处理。我们希望本节至少能让你意识到测试的必要性,并种下种子,激励你去学习更多。

测试本身并不重要。重要的是如何处理失败或成功。因为我们正在编写一个自定义的构建操作,所以我们可以在运行测试之前添加一个步骤。如果测试失败,构建将失败,部署将不会发生。

好消息是:因为我们正在使用 Vite,Vite 已经提供了一个很好的集成测试工具:Vitest

让我们开始吧。

  1. 安装 Vitest
    bash
    npm install --save-dev vitest
    
  2. 在你的 package.json 中,找到你的 scripts 成员,并更新它,使其包含以下测试和构建命令
    json
    "scripts": {
      // …
      "test": "vitest"
    }
    

    注意:这是使用 Vite 与 Vitest 的好处:如果你使用其他测试框架,你需要添加另一个配置来描述如何转换测试文件,但 Vitest 会自动使用 Vite 配置。

  3. 现在,我们当然需要将测试添加到我们的代码库中。通常,如果你正在测试某个文件的函数,比如 App.jsx,你可以在它旁边添加一个名为 App.test.jsx 的文件。在本例中,我们只是在测试数据,所以让我们创建一个另一个目录来存放我们的测试。你可以打开你在上一章下载的示例仓库,并将 tests 文件夹复制过来。
  4. 现在要手动运行测试,我们可以在命令行中运行
    bash
    npm run test
    
    你应该看到类似于这样的输出
    > [email protected] test
    > vitest
    
    
    DEV  v1.6.0 /Users/joshcena/Desktop/work/Tech/projects/mdn/client-toolchain-example
    
    ✓ tests/api.test.js (1) 896ms
      ✓ GitHub API returns the right response 896ms
    
    Test Files  1 passed (1)
         Tests  1 passed (1)
      Start at  23:12:25
      Duration  1.03s (transform 15ms, setup 0ms, collect 5ms, tests 896ms, environment 0ms, prepare 38ms)
    
    
    PASS  Waiting for file changes...
          press h to show help, press q to quit
    
    这意味着测试通过了。就像 Vite 一样,它会监控更改并在你保存文件时重新运行测试。我们可以按 q 退出。
  5. 我们仍然需要将测试连接到我们的构建操作,这样如果测试失败,它就会阻止构建。打开 .github/workflows/github-pages.yml 文件(或你为构建操作指定的任何文件名)并添加以下步骤,就在运行 npm run build 的步骤之前
    yaml
    - name: Install deps
      run: npm ci
    
    # Add this
    - name: Run tests
      run: npm run test
    
    - name: Build
      run: npm run build
    
    这将在构建步骤之前运行测试。如果测试失败,构建将失败,部署将不会发生。
  6. 现在让我们使用与之前类似的命令将新代码上传到 GitHub
    bash
    git add .
    git commit -m 'adding test'
    git push origin main
    
    在某些情况下,你可能想测试构建代码的结果(因为这并不完全是我们编写的原始代码),因此可能需要在构建命令之后运行测试。在你自己的项目中工作时,你需要考虑所有这些单独的方面。

最后,在推送后一分钟左右,GitHub Pages 将部署项目更新。但只有在通过了引入的测试的情况下才会部署。

总结

这就是我们的示例案例研究和模块的全部内容!我们希望你发现它有用。虽然要成为一名客户端工具大师还有很长的路要走,但我们希望本模块能让你迈出理解客户端工具的第一步,并让你有信心学习更多、尝试新事物。

让我们总结工具链的所有部分

  • 代码质量和维护由 ESLint 和 Prettier 执行。这些工具作为 devDependencies 通过 npm install --dev eslint prettier eslint-plugin-react ...(由于这个项目使用 React,所以需要 ESLint 插件)添加到项目中。
  • 代码质量工具读取两个配置文件:eslint.config.js.prettierrc
  • 在开发过程中,我们继续使用 npm 添加依赖项。Vite 开发服务器在后台运行,以监控更改并自动构建我们的源代码。
  • 部署通过将我们的更改推送到 GitHub(在 "main" 分支上)来处理,这会触发使用 GitHub Actions 构建和部署以发布项目。对于我们的实例,这个 URL 是 https://mdn.github.io/client-toolchain-example/;你将有自己的唯一 URL。
  • 我们还有一个简单的测试,如果 GitHub API 提要没有提供正确的格式数据,它就会阻止站点构建和部署。

对于那些想要挑战的人来说,可以考虑是否可以优化这个工具链的某些部分。一些需要问自己的问题

  • 我们是否可以只提取 plotly.js 中我们需要的功能?这将减少 JavaScript 包的大小。
  • 也许你想添加其他工具,比如用于类型检查的 TypeScript,或者用于 CSS 规范检查的 stylelint?
  • 是否可以将 React 替换为 更小的东西
  • 是否可以添加更多测试以防止错误的构建部署,比如 性能审核
  • 是否可以设置通知,让你知道新部署成功或失败?