🦊zeckli筆記

部署 Remix 應用到 Github Pages

2025 年 4 月 12 日

雖然 Remix 的設計觀點更傾向:Remix 應用搭配伺服器可以獲得最好的使用者體驗與效能,但許多真實需求是靜態、不需要 Server 的狀況,為了滿足此類需求 Remix 團隊推出了 SPA 模式,不過目前似乎只有 Vite 支援此模式。為了暸解 SPA 模式,我嘗試將 Remix 應用部署到 Github Pages 並將重點記錄下來。起初以為改動會很複雜,但實際重點只有兩個: 打包設定與 Github Actions 設定 ,若想直接看完整程式碼可以到這裡,細節則讓我在下面稍微展開說明。

修改打包設定

一開始提到目前只有 Vite 支援 SPA 模式,所以需要調整 vite.config.ts:


import { vitePlugin as remix } from '@remix-run/dev'
import { copyFileSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'

const repo = '/remix-gh-pages/'

export default defineConfig({
  base: repo,
  plugins: [
    remix({
      basename: repo,
      ssr: false,
    }),
    tsconfigPaths()
  ],
})
          

首先,SPA 模式需要將 SSR 關閉,這會讓 Vite 打包時只會產生前端相關的程式碼,也因此當程式碼中有 Server API 相關如 loader 或 action 的情況下,執行建置時會出現出現錯誤。除此之外,Github Pages 讀取靜態資源時不是讀取根目錄 / 而是 /your-repo-name/,所以在打包設定裡一起將 base 與 basename 做了調整。


若建置順利完成,在資料夾 build/client 裡可以看到 index.html 與其他的前端資源。當稍後利用 Github Actions 上傳這些程式碼到 Github Pages,Github Pages 就會以這個 index.html 做為應用的進入點。


最後補充,當 Github Pages 遇到 404 錯誤時會去找有沒有客製的 404.html,所以可以在 Vite 建置時加入複製 index.html 為 404.html,這樣即使不是從 / 或不存在的路由進入,Remix 應用還是能正常運作而不是進入 Github 預設的 404 頁面。複製步驟可以這樣加:


...

const repo = '/remix-gh-pages/'

export default defineConfig({
  base: repo,
  plugins: [
    remix({
      basename: repo,
      ssr: false,
      buildEnd({ viteConfig }) {
        if (!viteConfig.isProduction) {
          return
        }

        const buildPath = viteConfig.build.outDir
        copyFileSync(
          join(buildPath, 'index.html'),
          join(buildPath, '404.html'),
        )
      }
    }),
    tsconfigPaths()
  ],
})
          

新增 Github Actions 設定檔

Github Actions 相關的設定在官方文件已有許多參考,這裡就直接放上我的設定檔 deploy.yml,但需要注意上傳的程式碼是 build/client 內的就好。


name: Deploy Remix App to Github Pages

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  build-and-deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - uses: pnpm/action-setup@v2
        with:
          version: 8
          run_install: true

      - uses: actions/configure-pages@v4

      - run: pnpm build
      
      - uses: actions/upload-pages-artifact@v3
        with:
          path: 'build/client'

      - id: deployment
        uses: actions/deploy-pages@v4
          

如果部署後一直顯示 README.md 的內容,記得去設定裡的 Pages 把 Source 改為 Github Actions。希望內容有幫助,感謝閱讀!