從 Vite 遷移至 Next.js
本指南將協助您將現有的 Vite 應用程式遷移至 Next.js。
為什麼要切換?
從 Vite 切換到 Next.js 有以下幾個原因:
初始頁面載入時間緩慢
如果您使用 Vite 的預設 React 外掛 建置應用程式,您的應用程式將是一個純客戶端應用程式。純客戶端應用程式(也稱為單頁應用程式 (SPA))通常會遇到初始頁面載入時間緩慢的問題。這是由以下幾個原因造成的:
- 瀏覽器需要等待 React 程式碼和整個應用程式套件下載並執行後,您的程式碼才能發送請求載入資料。
- 應用程式程式碼會隨著新增功能和額外依賴項而不斷增長。
沒有自動程式碼分割
初始載入時間緩慢的問題可以透過程式碼分割來部分解決。然而,如果嘗試手動進行程式碼分割,往往會讓效能變得更糟。手動程式碼分割很容易無意中引入網路瀑布效應。Next.js 在其路由器中內建了自動程式碼分割功能。
網路瀑布效應
效能不佳的一個常見原因是應用程式為了獲取資料而進行連續的客戶端-伺服器請求。在 SPA 中獲取資料的一個常見模式是初始渲染一個佔位符,然後在元件掛載後獲取資料。不幸的是,這意味著獲取資料的子元件必須等到父元件完成載入自己的資料後才能開始獲取。
雖然 Next.js 支援在客戶端獲取資料,但它也提供了將資料獲取移至伺服器的選項,這可以消除客戶端-伺服器的瀑布效應。
快速且有意義的載入狀態
透過內建的 透過 React Suspense 進行串流 支援,您可以更有意義地決定 UI 的哪些部分要優先載入以及載入順序,而不會引入網路瀑布效應。
這使您能夠建置載入速度更快的頁面,並消除 版面偏移。
選擇資料獲取策略
根據需求,Next.js 允許您在頁面和元件基礎上選擇資料獲取策略。您可以決定在建置時、伺服器請求時或在客戶端獲取資料。例如,您可以從 CMS 獲取資料並在建置時渲染部落格文章,然後將其高效地快取在 CDN 上。
中介軟體
Next.js 中介軟體 允許您在請求完成前在伺服器上執行程式碼。這對於避免使用者在訪問需要驗證的頁面時看到未驗證內容的閃爍特別有用,可以將使用者重定向到登入頁面。中介軟體也適用於實驗和 國際化。
內建優化
圖片、字型 和 第三方腳本 通常對應用程式的效能有重大影響。Next.js 提供了內建元件,可以自動為您優化這些內容。
遷移步驟
本次遷移的目標是盡快獲得一個可運行的 Next.js 應用程式,以便您可以逐步採用 Next.js 的功能。首先,我們將其保留為純客戶端應用程式 (SPA),不遷移現有的路由。這有助於最小化遷移過程中遇到問題的機會,並減少合併衝突。
步驟 1:安裝 Next.js 依賴項
首先需要安裝 next
作為依賴項:
步驟 2:建立 Next.js 設定檔
在專案根目錄下建立 next.config.mjs
檔案。此檔案將包含您的 Next.js 設定選項。
須知: 您可以使用
.js
或.mjs
作為 Next.js 設定檔的副檔名。
步驟 3:更新 TypeScript 設定
如果您使用 TypeScript,需要更新 tsconfig.json
檔案以使其與 Next.js 相容。如果不使用 TypeScript,可以跳過此步驟。
- 移除對
tsconfig.node.json
的 專案參考 - 將
./dist/types/**/*.ts
和./next-env.d.ts
新增至include
陣列 - 將
./node_modules
新增至exclude
陣列 - 在
compilerOptions
的plugins
陣列 中新增{ "name": "next" }
:"plugins": [{ "name": "next" }]
- 將
esModuleInterop
設為true
:"esModuleInterop": true
- 將
jsx
設為preserve
:"jsx": "preserve"
- 將
allowJs
設為true
:"allowJs": true
- 將
forceConsistentCasingInFileNames
設為true
:"forceConsistentCasingInFileNames": true
- 將
incremental
設為true
:"incremental": true
以下是包含這些變更的 tsconfig.json
範例:
您可以在 Next.js 文件 中找到更多關於設定 TypeScript 的資訊。
步驟 4:建立根佈局
Next.js App Router 應用程式必須包含一個 根佈局 檔案,這是一個 React 伺服器元件,它將包裹應用程式中的所有頁面。此檔案定義在 app
目錄的頂層。
Vite 應用程式中最接近根佈局檔案的是 index.html
檔案,它包含您的 <html>
、<head>
和 <body>
標籤。
在此步驟中,您將把 index.html
檔案轉換為根佈局檔案:
- 在
src
目錄中建立一個新的app
目錄。 - 在該
app
目錄中建立一個新的layout.tsx
檔案:
須知:佈局檔案可以使用
.js
、.jsx
或.tsx
副檔名。
- 將
index.html
檔案的內容複製到先前建立的<RootLayout>
元件中,同時將body.div#root
和body.script
標籤替換為<div id="root">{children}</div>
:
- Next.js 預設已包含 meta charset 和 meta viewport 標籤,因此您可以安全地從
<head>
中移除這些內容:
- 任何 中繼資料檔案 如
favicon.ico
、icon.png
、robots.txt
只要放置在app
目錄的頂層,就會自動新增到應用程式的<head>
標籤中。將 所有支援的檔案 移至app
目錄後,您可以安全地刪除它們的<link>
標籤:
- 最後,Next.js 可以透過 中繼資料 API 管理您的最後幾個
<head>
標籤。將您的最終中繼資料資訊移至匯出的metadata
物件:
透過上述變更,您從在 index.html
中宣告所有內容轉變為使用 Next.js 內建的基於慣例的方法(中繼資料 API)。這種方法使您能夠更輕鬆地提升頁面的 SEO 和網路分享性。
步驟 5:建立入口頁面
在 Next.js 中,您可以透過建立 page.tsx
檔案來宣告應用程式的入口點。這與 Vite 中最接近的檔案是您的 main.tsx
檔案。在此步驟中,您將設定應用程式的入口點。
- 在
app
目錄中建立[[...slug]]
目錄。
由於本指南的目標是首先將 Next.js 設定為 SPA (單頁應用程式),您需要讓頁面入口點捕捉應用程式的所有可能路由。為此,請在 app
目錄中建立一個新的 [[...slug]]
目錄。
此目錄稱為
可選的全面捕捉路由區段。
Next.js 使用基於檔案系統的路由器,其中
目錄用於定義路由。
這個特殊目錄將確保應用程式的所有路由都會指向其包含的 page.tsx
檔案。
- 在
app/[[...slug]]
目錄中建立一個新的page.tsx
檔案,內容如下:
小知識:頁面檔案可以使用
.js
、.jsx
或.tsx
副檔名。
此檔案是一個 伺服器元件 (Server Component)。當您執行 next build
時,此檔案會被預渲染為靜態資源。它_不需要_任何動態程式碼。
此檔案匯入了我們的全局 CSS,並告訴 generateStaticParams
我們只會生成一個路由,即位於 /
的索引路由。
現在,讓我們移動其餘的 Vite 應用程式,這些部分將僅在客戶端執行。
此檔案是一個 客戶端元件 (Client Component),由 'use client'
指令定義。客戶端元件在發送到客戶端之前仍會在伺服器上 預渲染為 HTML。
由於我們希望一開始建立一個僅在客戶端運行的應用程式,我們可以配置 Next.js 以禁用從 App
元件開始的預渲染。
現在,更新您的入口頁面以使用新元件:
步驟 6:更新靜態圖片匯入
Next.js 處理靜態圖片匯入的方式與 Vite 略有不同。在 Vite 中,匯入圖片檔案會返回其公共 URL 作為字串:
在 Next.js 中,靜態圖片匯入會返回一個物件。該物件可以直接與 Next.js 的 <Image>
元件 一起使用,或者您可以使用物件的 src
屬性與現有的 <img>
標籤。
<Image>
元件具有 自動圖片優化 的額外優勢。<Image>
元件會根據圖片的尺寸自動設定結果 <img>
的 width
和 height
屬性。這可以防止圖片載入時的版面位移。然而,如果您的應用程式包含僅設定其中一個尺寸而另一個尺寸未設定為 auto
的圖片,這可能會導致問題。當未設定為 auto
時,尺寸將預設為 <img>
尺寸屬性的值,這可能導致圖片顯示失真。
保留 <img>
標籤將減少應用程式中的變更量並避免上述問題。您可以稍後選擇性地遷移到 <Image>
元件,以透過 配置載入器 (loader) 來利用圖片優化,或者轉移到具有自動圖片優化的預設 Next.js 伺服器。
- 將從
/public
匯入的圖片的絕對匯入路徑轉換為相對匯入:
- 將圖片的
src
屬性而非整個圖片物件傳遞給您的<img>
標籤:
或者,您可以根據檔案名稱參考圖片資源的公共 URL。例如,public/logo.png
將為您的應用程式提供 /logo.png
的圖片,這將是 src
值。
警告: 如果您使用 TypeScript,在存取
src
屬性時可能會遇到類型錯誤。您可以暫時安全地忽略這些錯誤。它們將在本指南結束時修復。
步驟 7:遷移環境變數
Next.js 支援類似於 Vite 的 .env
環境變數。主要區別在於用於在客戶端公開環境變數的前綴。
- 將所有帶有
VITE_
前綴的環境變數更改為NEXT_PUBLIC_
。
Vite 在特殊的 import.meta.env
物件上公開了一些內建的環境變數,這些變數不受 Next.js 支援。您需要按以下方式更新它們的使用:
import.meta.env.MODE
⇒process.env.NODE_ENV
import.meta.env.PROD
⇒process.env.NODE_ENV === 'production'
import.meta.env.DEV
⇒process.env.NODE_ENV !== 'production'
import.meta.env.SSR
⇒typeof window !== 'undefined'
Next.js 也不提供內建的 BASE_URL
環境變數。但是,如果您需要,仍然可以配置一個:
- 將以下內容添加到您的
.env
檔案中:
- 在您的
next.config.mjs
檔案中將basePath
設定為process.env.NEXT_PUBLIC_BASE_PATH
:
- 將
import.meta.env.BASE_URL
的使用更新為process.env.NEXT_PUBLIC_BASE_PATH
步驟 8:更新 package.json
中的腳本
您現在應該能夠運行您的應用程式來測試是否成功遷移到 Next.js。但在那之前,您需要使用 Next.js 相關命令更新 package.json
中的 scripts
,並將 .next
和 next-env.d.ts
添加到您的 .gitignore
:
現在運行 npm run dev
,並打開 http://localhost:3000
。您應該會看到您的應用程式現在在 Next.js 上運行。
範例: 查看 此拉取請求 以獲取從 Vite 遷移到 Next.js 的實際範例。
步驟 9:清理
您現在可以從程式碼庫中清理與 Vite 相關的內容:
- 刪除
main.tsx
- 刪除
index.html
- 刪除
vite-env.d.ts
- 刪除
tsconfig.node.json
- 刪除
vite.config.ts
- 解除安裝 Vite 相依套件
後續步驟
如果一切按計劃進行,您現在有一個運作正常的 Next.js 應用程式,作為單頁應用程式運行。然而,您尚未利用 Next.js 的大部分優勢,但現在您可以開始進行增量變更以獲得所有好處。以下是您接下來可能想做的事情: