iT邦幫忙

1

【Github Pages & NextJS】GitHub Action CICD+ NextJS靜態打包部署GitHub Pages 步驟教學&踩坑紀錄

  • 分享至 

  • xImage
  •  

大家好,我是一宵三筵
近期練習了將NextJS的小專案打包成靜態檔,透過CICD放到GitHub Pages上的操作
但因為卡了一些坑弄了一整個晚上,因此來分享分享

先預告坑的部分:

  1. 在NextJS所打包的靜態檔&資源檔路徑對應問題
  2. GitHub目前實驗性的yml自動建立功能還有問題

文章會先整個介紹&紀錄流程,最後再跟大家分享這兩個問題要怎麼處理

另外我本身也不熟CICD的部分,因此學習上是使用ChatGPT處理
有ChatGPT和GitHub的新功能輔助下,不用學著寫
但最後的坑還是各種翻資料、找別人的討論才找到的

沒問題的話就Go Go!

GitHub Pages

簡介

簡單介紹一下GitHub Pages
他是GitHub所提供的一個針對靜態網頁託管服務

也就是能夠將那些專案build之後,打包成單純的html、JS、CSS之後
提供你一個domain name,讓你把網站放上去,方便提供給所有人看的一個服務

一般來說,要進行網站託管是需要花錢的(租用伺服器)
即使不租用,要設定一個domain name也是要花錢的
但是GitHub Pages直接免費提供你這些服務!

前置動作 - 專案上GitHub

要使用這個服務,首先要先確定你的專案有放上GitHub

有關GitHub的使用教學以及創建repository等等,可以去找其他教學文章
或是看我這邊這篇:【Day14】ChatGPT請教教我:GitHub!Git Flow!團隊協作!(下)

我這邊就先不贅述教學

開始進行 GitHub Pages 設定

首先進到要處理的專案頁面內,然後在上排找到這個Setting按鈕,給他按下去
https://ithelp.ithome.com.tw/upload/images/20240304/201357505j3jG2mxfJ.png

接著在左邊的列表中,找到「Pages」的選項,就會看到GitHub Pages相關的設定
https://ithelp.ithome.com.tw/upload/images/20240304/20135750it4ZjCNqm9.png

接著點一下紅框中圈起來的「Deploy from a branch」,選擇點擊GitHub Actions
https://ithelp.ithome.com.tw/upload/images/20240304/20135750KV2DnDndwx.png

這個是一個GitHub正在實驗性的功能
根據你專案的框架與內容,自動配對、生成對應的 cicd所需的 yml檔
像下圖這樣,他馬上自動偵測到我所使用的是NextJS,並提供了相應的設定
https://ithelp.ithome.com.tw/upload/images/20240304/20135750STmGI4cwSn.png

按下圖中框選起來的Configure按鈕後,會進入下圖的頁面
https://ithelp.ithome.com.tw/upload/images/20240304/20135750HXymb7EbUe.png

這份nextjs.yml內容是GitHub Action自動提供的指令,來告訴後面介紹的GitHub Action 應該怎麼做部署打包的步驟
先不用細看這份資料,按下右上角的「Commit changes」
https://ithelp.ithome.com.tw/upload/images/20240304/20135750bjUr9NHJt9.png
繼續按下「Commit changes」

GitHub Action

做完剛剛的事情之後,我們的專案內就會有一個 nextjs.yml
有了這個檔案,接下來的每次push,就會讓GitHub Action 的服務進行相對應的指定與動作
https://ithelp.ithome.com.tw/upload/images/20240304/20135750214vfYGd8R.png

上圖是我的紀錄,每一次的push就會加上一行,並顯示執行進度與結果
按照剛剛的步驟的話,會找到我們剛剛commit的名稱「Create nextjs.yml 」

前面的符號沒有意外的話會是 紅色的叉叉
點進來的話,會看到像是這樣的頁面
https://ithelp.ithome.com.tw/upload/images/20240304/20135750Y9rTY79RSs.png
這邊就是GitHub Action 根據我們的yml檔所做的動作步驟與結果

可以看到build是失敗的,所以我們點進去紅色框選的位置看看
https://ithelp.ithome.com.tw/upload/images/20240304/20135750FmJRokiCv4.png

這裡就可以更詳細看到所有步驟的執行顯示內容,以及錯誤的訊息
可以看到我們剛剛跑起來的錯誤訊息長這樣:

Run npx --no-install next export
⨯ 
The "next export" command has been removed in favor of "output: export" in next.config.js. Learn more: https://nextjs.org/docs/advanced-features/static-html-export
Error: Process completed with exit code 1.

預告一下,中間過程還有可能遇到這個問題:
https://ithelp.ithome.com.tw/upload/images/20240304/20135750QGha14gHwp.png

Run actions/upload-pages-artifact@v3
Run echo ::group::Archive artifact
Archive artifact
tar: out: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now
Error: Process completed with exit code 2.

接下來會一口氣修復所有問題,所以第二個錯誤訊息不會看到
但如果是卡在第二個問題的朋友,也可以跟著改看看

踩坑&修復

首先第一個「Static HTML export with Next.js」的錯誤項目內容意思是說:
「next export」這個指令已經被NextJS廢棄了。
但是GitHub Action送我們的那個yml檔裡面,仍然有使用到這個指令來進行來進行打包處理

因此我們要來找出一些在 .github/workflows/nextjs.yml 裡面需要被移除、修掉的指令
以及在next的confing檔中必須追加的設定

  1. .github/workflows/nextjs.yml
    在github自動生成的那份nextjs.yml檔中,找到以下兩段部分
    並使用 # 註解掉(或是直接刪掉)

    - name: Static HTML export with Next.js
    run: ${{ steps.detect-package-manager.outputs.runner }} next export
    
    with:
       # Automatically inject basePath in your Next.js configuration file and disable
       # server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized).
       #
       # You may remove this line if you want to manage the configuration yourself.
       static_site_generator: next
    

    第二段註解掉之後,上圖的第二個「Upload artifact」的錯誤就不會出現了

  2. next.config.mjs
    找到next.config 檔案,並在nextConfig物件中加入以下幾行

    /** @type {import('next').NextConfig} */
    const nextConfig = {
       output: 'export',
       reactStrictMode: true,
       assetPrefix: 'https://lalame888.github.io/minesweeper-react/'
     }
    export default nextConfig
    

    其中那個'https://lalame888.github.io/minesweeper-react/' 的部分
    換上你的Pages URL
    (格式是https:// + [你的github帳號] + .github.io/ + [Repository名稱]

為了顧及本地開發的話,也可以加上判斷環境變數的判斷,變成以下這樣

/** @type {import('next').NextConfig} */

const isProd = process.env.NODE_ENV === 'production'

const nextConfig = {
  output: isProd ? 'export' : undefined,
  reactStrictMode: true,
  assetPrefix: isProd
    ? 'https://lalame888.github.io/minesweeper-react/'
    : undefined
}
export default nextConfig

微微解釋一下為什麼要加上這些

  • output: 'export' :指定bulid的時候變成靜態檔,靜態檔預設會放在./out的資料夾下
    (如果要改變這個資料夾名稱或位置,就指定distDir: '[新資料夾名稱]' 的屬性)
  • reactStrictMode: true :Next.js 運行時符合嚴格模式
  • assetPrefix:載入靜態資源檔的前置路徑

第三點真的是一個大坑,事情是這樣的
假設當我們都成功之後,主頁路徑會是'https://lalame888.github.io/minesweeper-react/'的情況來說

理論上我們的靜態檔位置應該是'https://lalame888.github.io/minesweeper-react/_next/static/'下的位置
但是!沒有指定前綴的情況下,他會放在網域的根目錄,也就是
https://lalame888.github.io/_next/static/ 這個位置下
中間整整少了自己的Repository名稱,就會造成所有的js、css等資源檔都是載入失敗的

而且目前測試來說,若是只放assetPrefix: '/minesweeper-react/'
雖然路徑看起來是對的了,但是還是會觸發NextJS的 PageRouter,拿到404的錯誤訊息
https://ithelp.ithome.com.tw/upload/images/20240304/201357502Tp7P5b7eJ.png

https://ithelp.ithome.com.tw/upload/images/20240304/20135750zneitYl8y5.png

結語

以上,就是目前使用GitHub Action 自動建置的yml檔進行NextJS靜態打包&部署的步驟教學&踩坑紀錄,繁中的資源不多,希望可以幫上同樣卡在這些步驟的人

而且有關這個yml暫時我不太建議使用ChatGPT-3.5生成,主要有兩個原因:

  1. 版本問題:
    ChatGPT生成的yml檔,所使用的NodeJS還在NodeJS 16版
    actions/checkout 還在使用v2
    部署部分使用的是 JamesIves/github-pages-deploy-action 的v3版本

    這些舊版本的action都會有版本過舊、指令過舊的問題
    或是建議的config選項已經被NextJS廢棄

  2. 參數名稱錯誤、另外指定token
    可能是和gitlab的指令搞混或是和其他的指令搞混,yml中有些參數名稱是錯誤的
    還要一來一回跟ChatGPT將錯誤訊息貼上慢慢找bug

    而且明明GitHub已經有預設的GITHUB_TOKEN 是授權給GitHub Action使用的
    但ChatGPT的教學中,讓我另外去申請Personal access tokens並進行secrets設定

    這些步驟完全繞了一大圈。

  3. 最後仍然沒有成功排除我的問題

最後,本次示範的專案也順便貼出來,是一個極其簡單的踩地雷小遊戲
而且其實是一個公司的面試小作業

Repository: https://github.com/lalame888/minesweeper-react
GitHub pages: https://lalame888.github.io/minesweeper-react/

若是好奇我與ChatGPT的曲折對話的話,也可以看這個
https://chat.openai.com/share/3c24e88c-054f-4faf-80d1-0f7cfe9729b2

但是ChatGPT所提供的教學最後被我完全棄用!並且有上述說的那一些問題
所以可以看看那些曲折對話,但不建議照著做

真的要說好處,應該是我可以快速理解設定步驟
對於我這個真的完全不熟GitHub Action與CICD的人
也能了解若是使用自建的yml的步驟、yml的樣貌與作用等等

但真的繞太大圈了,版本上的問題太嚴重了。不推。

參考資料


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
周藍
iT邦新手 5 級 ‧ 2024-03-20 23:26:26

謝謝!我目前變成寫死 assetPrefix: 'https://lalame888.github.io/minesweeper-react/'
這樣才解決靜態檔&資源路徑的問題
但上述提供的方法,看起來是去追加.nojekyll來設置
看起來作法更固定更通用一點
感謝你~~

我要留言

立即登入留言