部署我們的應用

在本系列的最後一篇文章中,我們將利用上一篇文章中構建的示例工具鏈,並在此基礎上進行擴充套件,以便部署我們的示例應用程式。我們將程式碼推送到 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 screenshot showing remote URLs you can use to deploy code to a GitHub repo

  5. 在將此遠端位置推送到 GitHub 之前,我們需要將其新增到本地 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 倉庫,工具鏈的下一步是定義一個構建操作,以便我們的專案可以即時部署到 Web 上!

使用 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://.github.io/`。對於我們的示例,它位於 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
    

    你應該會看到這樣的輸出

    > client-toolchain-example@1.0.0 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 執行。這些工具透過 `npm install --dev eslint prettier eslint-plugin-react ...` 作為 `devDependencies` 新增到專案中(因為這個特定專案使用 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 linting 的 stylelint?
  • React 能否替換為 更小的替代品
  • 你能否新增更多測試來阻止不良構建的部署,例如 效能審計
  • 您能否設定一個通知,讓您知道新的部署是成功還是失敗?