跳到內容
返回部落格

2022 年 10 月 25 日 星期二

Next.js 13

發布者

如同我們在 Next.js Conf 上宣布的,Next.js 13 (穩定版) 為無限動態的可能性奠定了基礎

Next.js 13 和 pages 目錄皆已穩定,可供生產環境使用。立即執行以下指令更新:

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

全新 app 目錄 (Beta)

今天,我們推出 app 目錄,旨在改善 Next.js 中的路由和版面配置體驗,並與 React 的未來發展方向保持一致。這是先前發布以徵求社群回饋的版面配置 RFC 的後續。

app 目錄目前為 beta 版本,我們不建議在生產環境中使用。您可以繼續使用 Next.js 13 和 pages 目錄,並享有已穩定功能,例如改良的 next/imagenext/link 元件,並以您自己的步調選擇是否採用 app 目錄。pages 目錄在可預見的未來將會繼續受到支援。

app 目錄包含以下支援:

  • 版面配置: 在路由之間輕鬆共享 UI,同時保留狀態並避免昂貴的重新渲染。
  • 伺服器元件: 將伺服器優先作為最動態應用程式的預設選項。
  • 串流: 顯示即時載入狀態,並在 UI 渲染完成時以單元串流方式傳輸。
  • 資料獲取支援: async 伺服器元件和擴展的 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 全新伺服器元件架構的支援。伺服器元件和用戶端元件分別利用伺服器和用戶端的優勢,讓您可以使用單一程式設計模型建構快速、高度互動的應用程式,並提供出色的開發人員體驗。

透過伺服器元件,我們為建構複雜介面奠定了基礎,同時減少發送到客戶端的 JavaScript 數量,從而加快初始頁面載入速度。

當路由載入時,將會載入 Next.js 和 React 運行時,它們是可快取的且大小可預測的。此運行時不會隨著應用程式的成長而增加大小。此外,運行時是異步載入的,使伺服器傳來的 HTML 能夠在客戶端上逐步增強。

深入瞭解伺服器元件部署範例來試用看看

串流

app/ 目錄引入了逐步渲染和以增量串流方式將渲染完成的 UI 單元傳輸到用戶端的功能。

透過 Next.js 中的伺服器元件和巢狀版面配置,您可以立即渲染頁面中不需要特定資料的部分,並為正在獲取資料的頁面部分顯示載入狀態。透過這種方法,使用者不必等待整個頁面載入完成即可開始與之互動。

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 支援 引入了一種強大的新方法,可以在元件內部獲取資料和處理 promise

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 中擴展。它會自動重複資料刪除 fetch 請求,並提供一種彈性的方式來獲取、快取和重新驗證元件級別的資料。這表示靜態網站生成 (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 生態系統做出貢獻的公司合作,為 React 和 Next.js 的新時代而努力。將資料獲取與元件放在一起,並減少發送到用戶端的 JavaScript 數量,是社群回饋中非常重要的兩點,我們很高興能將其納入 app/ 目錄中。

深入瞭解資料獲取部署範例來試用看看

隆重推出 Turbopack (Alpha)

Next.js 13 包含 Turbopack,這是以 Rust 為基礎的全新 Webpack 後繼者。

Webpack 的下載次數已超過 30 億次。雖然它一直是建構網路不可或缺的一部分,但我們已達到以 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 只捆綁開發中所需的最小資源,因此啟動時間非常快。在一個擁有 3,000 個模組的應用程式上,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 元件,並因此看到了 Core Web Vitals 的改善。在 Next.js 13 中,我們將進一步改進 next/image

新的 Image 元件

  • 減少客戶端 JavaScript 的傳輸量
  • 更易於設定樣式和配置
  • 更易於存取,預設需要 alt 標籤
  • 與 Web 平台保持一致
  • 速度更快,因為原生延遲載入不需要 hydration
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>,並允許您將 props 轉發到基礎標籤。例如

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.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 更新

在 Next.js 12 版本中,我們推出了 Middleware,讓 Next.js 路由器更具彈性。我們聽取了您對初始 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 提供回應,而無需使用 rewriteredirect

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 版本已終止生命週期 (PR)。
  • swcMinify 設定屬性已從 false 變更為 true。請參閱 Next.js Compiler 以取得更多資訊。
  • next/image 匯入已重新命名為 next/legacy/imagenext/future/image 匯入已重新命名為 next/image。有一個程式碼模組可用於安全且自動地重新命名您的匯入。
  • next/link 子元素不能再是 <a>。新增 legacyBehavior 屬性以使用舊版行為,或移除 <a> 以進行升級。有一個程式碼模組可用於自動升級您的程式碼。
  • 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 萬次,GitHub 星星數達到 94,000 顆,是建構網路最受歡迎的方式之一。

特別感謝 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。