跳至內文
返回部落格

星期二,2022 年 10 月 25 日

Next.js 13

張貼者

如同我們在 Next.js 大會 所宣布,Next.js 13 (穩定版) 奠定無限動態的基礎

Next.js 13 和 pages 目錄已穩定且準備好投入生產。立即透過執行更新

終端機
npm i next@latest react@latest react-dom@latest eslint-config-next@latest

新增 app 目錄 (測試版) 佈局 RFC 的後續行動,此前已發布以徵求社群意見。

app 目錄目前仍處於測試階段,我們不建議在實際環境中使用。您可以使用 Next.js 13 搭配 pages 目錄,使用已穩定的功能,例如經過改善的 next/imagenext/link 元件,並依照自己的步調選擇加入 app 目錄。pages 目錄在可預見的未來將持續獲得支援。

app 目錄包含以下支援功能

  • 佈局:跨路由輕鬆分享 UI,同時保留狀態並避免昂貴的重新渲染。
  • 伺服器元件:將伺服器優先作為預設值,以打造最動態的應用程式。
  • 串流:顯示即時載入狀態,並在元件渲染時串流 UI 單元。
  • 支援資料擷取:非同步伺服器元件和延伸的 fetch API 支援元件層級的擷取。
The app directory can be incrementally adopted from your existing pages/ directory.
app 目錄可以逐步從現有的 pages/ 目錄採用。

佈局

app/ 目錄有助於輕鬆配置複雜介面,可跨導覽維護狀態,避免昂貴的重新渲染,並支援進階路由模式。此外,您可以嵌套佈局,並將應用程式程式碼與路由設定在同一處,例如元件、測試和樣式。

The app/ directory can be incrementally adopted from your existing pages/ directory.
app/ 目錄可以逐步從現有的 pages/ 目錄採用。

app/ 內部建立路由需要一個檔案,page.js

app/page.js
// This file maps to the index route (/)
export default function Page() {
  return <h1>Hello, Next.js!</h1>;
}

然後您可以透過檔案系統定義佈局。佈局可在多個頁面之間共用 UI。在導覽時,佈局會保留狀態、維持互動性,而且不會重新渲染。

app/blog/layout.js
export default function BlogLayout({ children }) {
  return <section>{children}</section>;
}

了解更多關於佈局與頁面的資訊,或 部署範例來試試看

伺服器元件

app/ 目錄引入了對 React 新 伺服器元件 架構的支援。伺服器和 用戶端元件 分別發揮各自的優勢,在伺服器和用戶端執行 - 讓您可以使用單一、提供絕佳開發人員體驗的程式設計模型來建置快速、高度互動的應用程式。

使用 Server Components,我們可以建立複雜介面的基礎,同時減少傳送到用戶端的 JavaScript 數量,讓初始頁面載入速度變快。

載入路徑時,Next.js 和 React 執行時間會載入,其具有快取可預知的大小。該執行時間不會隨著你的應用程式增長而增加。此外,執行時間會以非同步方式載入,讓來自伺服器的 HTML 能在用戶端逐步增強。

深入了解 Server Components部署範例來試用

串流

app/ 目錄引入了逐步渲染和遞增串流 UI 渲染單元到用戶端的能力。

透過 Next.js 中的 Server Components 和 巢狀配置,你可以立即渲染頁面中不需要特定資料的部分和顯示 載入狀態,供頁面中取用資料的部分。透過這種方式,使用者無需等到整個頁面載入後,才能開始與頁面進行互動。

You can colocate your application code, such as components, tests, and styles, with your routes.
你可以將你的應用程式程式碼,例如元件、測試和樣式,與你的路線並置。

當部署到 Vercel 時,使用 app/ 目錄的 Next.js 13 應用程式在 Node.js 和 Edge 執行時間中,會預設串流回應以提升效能。

深入了解串流部署範例來試用

資料提取

React 近期的 Promises RFC 支援 新增了取得資料和處理 promises 的強大新方法在元件內部

app/page.js
async function getData() {
  const res = await fetch('https://api.example.com/...');
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
  return res.json();
}
 
// This is an async Server Component
export default async function Page() {
  const data = await getData();
 
  return <main>{/* ... */}</main>;
}

原生的 fetch Web API 也已在 React 和 Next.js 中延伸。它 自動重複清除提取要求 並提供一個靈活的方式來提取、快取和驗證元件層級的資料。這表示所有靜態網站產生 (SSG)、伺服器端渲染 (SSR) 和遞增靜態產生 (ISR) 的優點現在都可透過一個 API 取得

// This request should be cached until manually invalidated.
// Similar to `getStaticProps`.
// `force-cache` is the default and can be omitted.
fetch(URL, { cache: 'force-cache' });
 
// This request should be refetched on every request.
// Similar to `getServerSideProps`.
fetch(URL, { cache: 'no-store' });
 
// This request should be cached with a lifetime of 10 seconds.
// Similar to `getStaticProps` with the `revalidate` option.
fetch(URL, { next: { revalidate: 10 } });

app 目錄中,可以在 佈局、頁面 和元件中擷取資料 - 包含伺服器 串流回應 的支援。

我們正啟用符合人體工學的方式來處理載入和錯誤狀態,並在渲染時串流 UI。在未來的版本中,我們也會改善和簡化資料變動,

With the app/ directory, you can use a new special file loading.js to automatically create Instant Loading UI with Suspense boundaries.
透過 app/ 目錄,你可以使用新的特殊檔案 loading.js 來自動建立帶有 Suspense 邊界的即時載入 UI。

我們很興奮能在這個 React 和 Next.js 新時代與開源社群、套件維護人員和其他為 React 生態系做出貢獻的公司合作開發功能。能夠將資料擷取作業與元件並置,並減少傳送到用戶端端的 JavaScript,是我們很興奮可以透過 app/ 目錄納入的兩個社群回饋。

瞭解更多關於資料擷取部署一個範例來試試

推出 Turbopack (Alpha 版)

Next.js 13 包含了 Turbopack,它是基於 Rust 的 Webpack 新繼承者。

Webpack 已被下載超過 30 億次。儘管它是建立 Web 不可或缺的一部分,但我們已經達到了基於 JavaScript 的工具所能達到的最高效能極限。

在 Next.js 12 中,我們開始轉換到基於原生 Rust 的工具。我們從遠離 Babel 開始,這使得轉譯速度提升了 17 倍。然後,我們替換了 Terser,這使縮小速度提升了 6 倍。現在是時候全面採用原生程式進行捆綁了。

在 Next.js 13 中使用 Turbopack Alpha 版會得到

  • 比 Webpack 快 700 倍 的更新速度
  • 比 Vite 快 10 倍的更新速度
  • 比 Webpack 快 4 倍的冷啟動速度
Turbopack is our Rust-based successor to Webpack, with 700x faster HMR for large applications.
Turbopack 我們基於 Rust 的 Webpack 繼承者,對於大型應用程式,它的 HMR 速度提升了 700 倍。

Turbopack 只會在開發中綑綁最少的必要的資源,因此啟動時間非常快。對於一個有 3000 個模組的應用程式,Turbopack 花費 1.8 秒 啟動。Vite 花費 11.4 秒,而 Webpack 花費 16.5 秒

Turbopack 從一開始就支援伺服器元件、TypeScript、JSX、CSS 等。在 alpha 期間,許多功能仍不支援。我們希望能收到您關於使用 Turbopack 加快本機反覆作業的意見回饋。

注意事項:Next.js 中的 Turbopack 目前僅支援 next dev。查看支援的功能。我們也正致力於透過 Turbopack 加入對 next build 的支援。

立即在 Next.js 13 中搭配 next dev --turbo 試用 Turbopack alpha。

next/image

Next.js 13 引進了強大的新 Image 元件,讓您可以輕鬆顯示影像而不會產生版面移位,還能依需要最佳化檔案,以提升效能。

在 Next.js 社群調查期間,70% 的受訪者告訴我們他們在製作環境中使用了 Next.js Image 元件,進而看到了核心網頁指標的改善。透過 Next.js 13,我們進一步強化了 next/image

新 Image 元件

  • 輸送較少的用戶端 JavaScript
  • 更容易調整樣式和設定
  • 更易於存取,預設需要 alt 標籤
  • 與網頁平台一致
  • 更快,因為原生延遲載入不需要與資料連線
app/page.js
import Image from 'next/image';
import avatar from './lee.png';
 
export default function Home() {
  // "alt" is now required for improved accessibility
  // optional: image files can be colocated inside the app/ directory
  return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}

深入了解 Image 元件,或部署一個範例來試用.

next/image 升級到 Next.js 13

舊的 Image 元件已重新命名為 next/legacy/image。我們提供了一種 codemod,它會自動將您現有的 next/image 使用情形更新為 next/legacy/image。例如,這個命令在從根目錄執行時,可以在 ./pages 目錄上執行 codemod

終端機
npx @next/codemod next-image-to-legacy-image ./pages

進一步了解 codemod.

@next/font

Next.js 13 引進了一個全新的字型系統,它

  • 自動最佳化你的字型,包括自訂字型
  • 移除外部網路請求,以改善隱私和效能
  • 內建自動自建置所有字型檔
  • 使用 CSS 屬性 size-adjust 自動完全避免版面變形

這個新的字型系統能讓你方便地使用所有 Google 字型,同時考慮到效能和隱私。CSS 和字型檔會在建置時下載,並與其他靜態資源一起自建置。瀏覽器不會向 Google 發送任何請求。

app/layout.js / pages/_app.js
import { Inter } from '@next/font/google';
 
const inter = Inter();
 
<html className={inter.className}></html>;

也支援自訂字型,包括自動自建置、快取和字型檔預載的支援。

app/layout.js / pages/_app.js
import localFont from '@next/font/local';
 
const myFont = localFont({ src: './my-font.woff2' });
 
<html className={myFont.className}></html>;

你可以自訂字型載入體驗的每個環節,同時依然能確保絕佳效能,且不會產生版面變形,包括 font-display、預載、備用字型,等等。

進一步了解新的 Font 元件部署一個範例來試試

next/link 不再需要手動加入 <a>作為子項。

這原先已在 12.2中作為實驗功能加入,現已改為預設。在 Next.js 13 中,<Link> 會永遠產生一個 <a>,並允許你將屬性轉發給底層標籤。例如

import Link from 'next/link'
 
// Next.js 12: `<a>` has to be nested otherwise it's excluded
<Link href="/about">
  <a>About</a>
</Link>
 
// Next.js 13: `<Link>` always renders `<a>`
<Link href="/about">
  About
</Link>

進一步了解改良後的 Link 元件部署一個範例來試試升級 next/link 到 Next.js 13

為連結升級到 Next.js 13,我們提供了 Codemod,它會自動更新你的程式碼庫。例如,這個指令會在從根目錄執行時,在你的 ./pages 目錄中執行 Codemod

終端機
npx @next/codemod new-link ./pages

進一步了解 codemod 或查看文件。

OG 圖片產生

社群卡(又稱為 Open Graph 圖片)能大幅提升你的內容點擊量,有些實驗顯示能夠提升最多 40% 的轉換率。

靜態社群卡費時、容易出錯而且難以維護。因此,很常會缺少社群卡甚至跳過。直到今天,需要個人化且即時運算的動態社群卡仍很困難且昂貴。

我們打造了一個新的函式庫 @vercel/og,它能與 Next.js 完美搭配,用來產生動態社群卡。

pages/api/og.jsx
import { ImageResponse } from '@vercel/og';
 
export const config = {
  runtime: 'experimental-edge',
};
 
export default function () {
  return new ImageResponse(
    (
      <div
        style={{
          display: 'flex',
          fontSize: 128,
          background: 'white',
          width: '100%',
          height: '100%',
        }}
      >
        Hello, World!
      </div>
    ),
  );
}

此種方法使用 Vercel Edge Functions、WebAssembly 以及全新的核心函式庫(用於將 HTML 和 CSS 轉換成圖片並運用 React 元件抽象),比現有解決方案 快上 5 倍

進一步了解 OG 圖片產生部署範例來試試

Middleware API 更新
middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
 
export function middleware(request: NextRequest) {
  // Clone the request headers and set a new header `x-version`
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-version', '13');
 
  // You can also set request headers in NextResponse.rewrite
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders,
    },
  });
 
  // Set a new response header `x-version`
  response.headers.set('x-version', '13');
  return response;
}

你現在也可以直接透過 Middleware 提供回應,而不需要重寫重新導向

middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { isAuthenticated } from '@lib/auth';
 
// Limit the middleware to paths starting with `/api/`
export const config = {
  matcher: '/api/:function*',
};
 
export function middleware(request: NextRequest) {
  // Call our authentication function to check the request
  if (!isAuthenticated(request)) {
    // Respond with JSON indicating an error message
    return NextResponse.json(
      {
        success: false,
        message: 'Auth failed',
      },
      {
        status: 401,
      },
    );
  }
}

目前,從 Middleware 傳送回應需要在 next.config.js 中加入 experimental.allowMiddlewareResponseBody 組態選項。

重大變更

  • 最低的 React 版本已從 17.0.2 提升至 18.2.0。
  • 最低的 Node.js 版本已從 12.22.0 提升至 14.6.0,因為 12.x 已達生命週期結束(公關)。
  • swcMinify 組態屬性已從 false 變更為 true。請參閱 Next.js Compiler 以取得更多資訊。
  • next/image 匯入已重新命名為 next/legacy/imagenext/future/image 匯入已重新命名為 next/image。有 可用的 codemod 可以安全地自動重新命名你的匯入。
  • next/link 子項目不再可以是 <a>。新增 legacyBehavior 屬性以使用舊版行為,或移除 <a> 以升級。有 可用的 codemod 可以自動升級你的程式碼。
  • User-Agent 是機器人時,路由不再進行預先讀取。
  • next.config.js 的舊版 target 選項已移除。
  • 已變更支援的瀏覽器以移除 Internet Explorer,並鎖定現代瀏覽器。你仍可以使用 Browserslist 變更目標瀏覽器。
    • Chrome 64+
    • Edge 79+
    • Firefox 67+
    • Opera 51+
    • Safari 12+

深入了解資訊,請查看 升級指南

社群

六年前,我們向大眾發布了 Next.js。我們打算建立一個無組態 React 框架,以簡化你的開發人員體驗。回顧過去,看到社群如何壯大,以及我們如何能夠攜手出貨,真是令人難以置信。讓我們持續前進。

Next.js 是超過 2,400 位個別開發者、Google 和 Meta 等業界合作夥伴和我們的核心團隊共同努力的成果。Next.js 每週有超過 300 萬次 npm 下載和 94,000 個 GitHub 星號,是建置網頁最受歡迎的方法之一。

特別感謝 Google Chrome 的 Aurora 團隊,他們協助進行了基礎研究和實驗,促成此版本的誕生。

此版本要感謝以下人員的貢獻:@ijjk、@huozhi、@HaNdTriX、@iKethavel、@timneutkens、@shuding、@rishabhpoddar、@hanneslund、@balazsorban44、@devknoll、@anthonyshew、@TomerAberbach、@philippbosch、@styfle、@mauriciomutte、@hayitsdavid、@abdennor、@Kikobeats、@cjdunteman、@Mr-Afonso、@kdy1、@jaril、@abdallah-nour、@North15、@feedthejim、@brunocrosier、@Schniz、@sedlukha、@hashlash、@Ethan-Arrowood、@fireairforce、@migueloller、@leerob、@janicklas-ralph、@Trystanr、@atilafassina、@nramkissoon、@kasperadk、@valcosmos、@henriqueholtz、@nip10、@jesstelford、@lorensr、@AviAvinav、@SukkaW、@jaycedotbin、@saurabhburade、@notrab、@kwonoj、@sanruiz、@angeloashmore、@falsepopsky、@fmontes、@Gebov、@UltiRequiem、@p13lgst、@Simek、@mrkldshv、@thomasballinger、@kyliau、@AdarshKonchady、@endymion1818、@pedro757、@perkinsjr、@gnoff、@jridgewell、@silvioprog、@mabels、@nialexsan、@feugy、@jackromo888、@crazyurus、@EarlGeorge、@MariaSolOs、@lforst、@maximbaz、@maxam2017、@teobler、@Nutlope、@sunwoo0706、@WestonThayer、@Brooooooklyn、@Nsttt、@charlypoly、@aprendendofelipe、@sviridoff、@jackton1、@nuta、@Rpaudel379、@marcialca、@MarDi66、@ismaelrumzan、@javivelasco、@eltociear 和 @hiro0218。