跳到主要內容
返回部落格

2023 年 10 月 26 日 星期四

Next.js 14

發布者:

如同我們在 Next.js Conf 上宣布的,Next.js 14 是我們最專注的版本,其中包含:

  • Turbopack:App & Pages Router 通過 5,000 項測試
    • 本地伺服器啟動速度提升 53%
    • 使用 Fast Refresh 程式碼更新速度提升 94%
  • 伺服器動作 (穩定版):漸進式增強的變更
    • 整合快取與重新驗證
    • 簡單的函式呼叫,或原生支援表單
  • 部分預先渲染 (預覽版):快速初始靜態回應 + 串流動態內容
  • Next.js Learn (全新):免費課程,教授 App Router、身份驗證、資料庫等。

立即升級或開始使用

終端機
npx create-next-app@latest

Next.js 編譯器:Turbocharged

自 Next.js 13 以來,我們一直致力於提升 Next.js 在 Pages 和 App Router 中的本地開發效能。

先前,我們為了支援這項努力,正在重寫 next dev 和 Next.js 的其他部分。 之後,我們已將方法改為更漸進式。 這表示我們基於 Rust 的編譯器將很快達到穩定,因為我們已將重點重新放在首先支援所有 Next.js 功能。

現在,next dev 的 5,000 項整合測試已通過我們底層的 Rust 引擎 Turbopack。 這些測試包含 7 年的錯誤修復和重現。

在大型 Next.js 應用程式 vercel.com 上進行測試時,我們觀察到

  • 本地伺服器啟動速度最高提升 53.3%
  • 使用 Fast Refresh 程式碼更新速度最高提升 94.7%

此基準測試是您在使用大型應用程式 (和大型模組圖) 時應預期的效能提升的實際結果。 隨著 next dev 現在通過 90% 的測試,當您使用 next dev --turbo 時,您應該會看到更快且更可靠的效能。

一旦我們達到 100% 的測試通過率,我們將在即將發布的次要版本中將 Turbopack 移至穩定版。 我們也將繼續支援使用 webpack 進行自訂設定和生態系統外掛程式。

您可以前往 areweturboyet.com 追蹤測試通過率。

表單與變更

Next.js 9 引入了 API 路由 — 一種在前端程式碼旁邊快速建構後端端點的方法。

例如,您會在 api/ 目錄中建立一個新檔案

pages/api/submit.ts
import type { NextApiRequest, NextApiResponse } from 'next';
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const data = req.body;
  const id = await createItem(data);
  res.status(200).json({ id });
}

然後,在用戶端,您可以使用 React 和事件處理常式 (例如 onSubmit) 來對您的 API 路由發出 fetch 請求。

pages/index.tsx
import { FormEvent } from 'react';
 
export default function Page() {
  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
 
    const formData = new FormData(event.currentTarget);
    const response = await fetch('/api/submit', {
      method: 'POST',
      body: formData,
    });
 
    // Handle response if necessary
    const data = await response.json();
    // ...
  }
 
  return (
    <form onSubmit={onSubmit}>
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  );
}

現在有了 Next.js 14,我們希望簡化開發人員撰寫資料變更的體驗。 此外,我們希望在使用者網路連線速度緩慢,或從低效能裝置提交表單時,改善使用者體驗。

伺服器動作 (穩定版)

如果您不需要手動建立 API 路由呢? 相反地,您可以定義一個在伺服器上安全執行的函式,直接從您的 React 元件中呼叫。

App Router 建構於 React Canary 通道之上,該通道對於框架採用新功能而言是 穩定的。 從 v14 開始,Next.js 已升級至最新的 React Canary,其中包括穩定的伺服器動作。

Pages Router 中的先前範例可以簡化為一個檔案

app/page.tsx
export default function Page() {
  async function create(formData: FormData) {
    'use server';
    const id = await createItem(formData);
  }
 
  return (
    <form action={create}>
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  );
}

對於任何先前使用過以伺服器為中心的框架的開發人員來說,伺服器動作應該會感到熟悉。 它建構於 Web 基礎知識之上,例如表單和 FormData Web API

雖然透過表單使用伺服器動作對於漸進式增強很有幫助,但這並非必要條件。 您也可以直接將它們作為函式呼叫,而無需表單。 使用 TypeScript 時,這可讓您在用戶端和伺服器之間獲得完整的端對端類型安全。

變更資料、重新渲染頁面或重新導向可以在一個網路往返中完成,即使上游供應商速度緩慢,也能確保在用戶端顯示正確的資料。 此外,您可以組合和重複使用不同的動作,包括在同一路由中包含許多不同的動作。

快取、重新驗證、重新導向及更多

伺服器動作已深度整合到整個 App Router 模型中。 您可以

  • 使用 revalidatePath()revalidateTag() 重新驗證快取資料
  • 透過 redirect() 重新導向至不同的路由
  • 透過 cookies() 設定和讀取 Cookie
  • 使用 useOptimistic() 處理樂觀 UI 更新
  • 使用 useFormState() 捕捉和顯示來自伺服器的錯誤
  • 使用 useFormStatus() 在用戶端顯示載入狀態

進一步瞭解使用伺服器動作的表單與變更,或關於伺服器元件和伺服器動作的安全性模型和最佳實務。

部分預先渲染 (預覽版)

我們想分享部分預先渲染的預覽版 — 一種針對動態內容的編譯器最佳化,具有快速的初始靜態回應 — 我們正在為 Next.js 開發。

部分預先渲染建立在十年來對伺服器端渲染 (SSR)、靜態網站產生 (SSG) 和增量靜態重新驗證 (ISR) 的研究和開發之上。

動機

我們已收到您的意見回饋。 目前有太多執行階段、設定選項和渲染方法需要考慮。 您希望擁有靜態的速度和可靠性,同時也支援完全動態、個人化的回應。

在全球範圍內擁有出色的效能和個人化,不應以複雜性為代價。

我們的挑戰是創造更好的開發人員體驗,簡化現有模型,而無需引入新的 API 供開發人員學習。 雖然伺服器端內容的部分快取已經存在,但這些方法仍然需要滿足我們旨在實現的開發人員體驗和可組合性目標。

部分預先渲染不需要學習新的 API。

建構於 React Suspense 之上

部分預先渲染由您的 Suspense 邊界定義。 以下是它的運作方式。 考慮以下電子商務頁面

app/page.tsx
export default function Page() {
  return (
    <main>
      <header>
        <h1>My Store</h1>
        <Suspense fallback={<CartSkeleton />}>
          <ShoppingCart />
        </Suspense>
      </header>
      <Banner />
      <Suspense fallback={<ProductListSkeleton />}>
        <Recommendations />
      </Suspense>
      <NewProducts />
    </main>
  );
}

啟用部分預先渲染後,此頁面會根據您的 <Suspense /> 邊界產生靜態外殼。 React Suspense 中的 fallback 會被預先渲染。

外殼中的 Suspense fallback 隨後會被動態元件取代,例如讀取 Cookie 以判斷購物車,或根據使用者顯示橫幅。

發出請求時,會立即提供靜態 HTML 外殼

<main>
  <header>
    <h1>My Store</h1>
    <div class="cart-skeleton">
      <!-- Hole -->
    </div>
  </header>
  <div class="banner" />
  <div class="product-list-skeleton">
    <!-- Hole -->
  </div>
  <section class="new-products" />
</main>

由於 <ShoppingCart /> 從 Cookie 讀取以查看使用者工作階段,因此此元件會與靜態外殼一起作為同一個 HTTP 請求的一部分串流傳輸。 無需額外的網路往返。

app/cart.tsx
import { cookies } from 'next/headers'
 
export default function ShoppingCart() {
  const cookieStore = cookies()
  const session = cookieStore.get('session')
  return ...
}

為了擁有最細緻的靜態外殼,這可能需要新增額外的 Suspense 邊界。 但是,如果您今天已經在使用 loading.js,這是一個隱含的 Suspense 邊界,因此無需進行任何變更即可產生靜態外殼。

即將推出

部分預先渲染正在積極開發中。 我們將在即將發布的次要版本中分享更多更新。

Metadata 改善

在您的頁面內容可以從伺服器串流傳輸之前,需要先將關於 viewport、色彩配置和主題的重要 metadata 傳送至瀏覽器。

確保這些 meta 標籤與初始頁面內容一起傳送,有助於提供流暢的使用者體驗,防止頁面因變更主題色彩而閃爍,或因 viewport 變更而導致版面配置偏移。

在 Next.js 14 中,我們已將封鎖和非封鎖 metadata 解耦。 只有一小部分 metadata 選項是封鎖的,我們希望確保非封鎖 metadata 不會阻止部分預先渲染的頁面提供靜態外殼。

以下 metadata 選項現在已棄用,並將在未來的主要版本中從 metadata 中移除

  • viewport:設定 viewport 的初始縮放和其他屬性
  • colorScheme:設定 viewport 的支援模式 (淺色/深色)
  • themeColor:設定 viewport 周圍的 Chrome 應渲染的色彩

從 Next.js 14 開始,有新的選項 viewportgenerateViewport 可取代這些選項。 所有其他 metadata 選項保持不變。

您可以從今天開始採用這些新的 API。 現有的 metadata 選項將繼續運作。

Next.js Learn 課程

今天,我們在 Next.js Learn 上發布了全新的免費課程。 本課程教授

  • Next.js App Router
  • 樣式與 Tailwind CSS
  • 最佳化字型和圖片
  • 建立版面配置和頁面
  • 在頁面之間導航
  • 設定您的 Postgres 資料庫
  • 使用伺服器元件提取資料
  • 靜態和動態渲染
  • 串流
  • 部分預先渲染 (選用)
  • 新增搜尋和分頁
  • 變更資料
  • 處理錯誤
  • 改善可存取性
  • 新增身份驗證
  • 新增 Metadata

Next.js Learn 已向數百萬開發人員教授了框架的基礎知識,我們迫不及待想聽到您對我們新增內容的意見回饋。 前往 nextjs.org/learn 修習課程。

其他變更

  • [重大變更] 最低 Node.js 版本現在為 18.17
  • [重大變更] 移除 next-swc 建置的 WASM 目標 (PR)
  • [重大變更] 移除對 @next/font 的支援,改用 next/font (Codemod)
  • [重大變更]ImageResponse 匯入從 next/server 變更為 next/og (Codemod)
  • [重大變更] next export 命令已移除,改用 output: 'export' 設定 (文件)
  • [已棄用] next/imageonLoadingComplete 已棄用,改用 onLoad
  • [已棄用] next/imagedomains 已棄用,改用 remotePatterns
  • [功能] 可以啟用圍繞 fetch 快取的更詳細記錄 (文件)
  • [改進] 基本 create-next-app 應用程式的函式大小縮小 80%
  • [改進] 在開發中使用 edge 執行階段時,增強的記憶體管理

貢獻者

Next.js 是超過 2,900 位個別開發人員、Google 和 Meta 等產業合作夥伴以及我們 Vercel 核心團隊共同努力的成果。 加入 GitHub DiscussionsRedditDiscord 上的社群。

此版本由以下團隊推出:

以及以下貢獻者: @05lazy、@0xadada、@2-NOW、@aarnadlr、@aaronbrown-vercel、@aaronjy、@abayomi185、@abe1272001、@abhiyandhakal、@abstractvector、@acdlite、@adamjmcgrath、@AdamKatzDev、@adamrhunter、@ademilter、@adictonator、@adilansari、@adtc、@afonsojramos、@agadzik、@agrattan0820、@akd-io、@AkifumiSato、@akshaynox、@alainkaiser、@alantoa、@albertothedev、@AldeonMoriak、@aleksa-codes、@alexanderbluhm、@alexkirsz、@alfred-mountfield、@alpha-xek、@andarist、@Andarist、@andrii-bodnar、@andykenward、@angel1254mc、@anonrig、@anthonyshew、@AntoineBourin、@anujssstw、@apeltop、@aralroca、@aretrace、@artdevgame、@artechventure、@arturbien、@Aryan9592、@AviAvinav、@aziyatali、@BaffinLee、@Banbarashik、@bencmbrook、@benjie、@bennettdams、@bertho-zero、@bigyanse、@Bitbbot、@blue-devil1134、@bot08、@bottxiang、@Bowens20832、@bre30kra69cs、@BrennanColberg、@brkalow、@BrodaNoel、@Brooooooklyn、@brunoeduardodev、@brvnonascimento、@carlos-menezes、@cassidoo、@cattmote、@cesarkohl、@chanceaclark、@charkour、@charlesbdudley、@chibicode、@chrisipanaque、@ChristianIvicevic、@chriswdmr、@chunsch、@ciruz、@cjmling、@clive-h-townsend、@colinhacks、@colinking、@coreyleelarson、@Cow258、@cprussin、@craigwheeler、@cramforce、@cravend、@cristobaldominguez95、@ctjlewis、@cvolant、@cxa、@danger-ahead、@daniel-web-developer、@danmindru、@dante-robinson、@darshanjain-entrepreneur、@darshkpatel、@davecarlson、@David0z、@davidnx、@dciug、@delbaoliveira、@denchance、@DerTimonius、@devagrawal09、@DevEsteves、@devjiwonchoi、@devknoll、@DevLab2425、@devvspaces、@didemkkaslan、@dijonmusters、@dirheimerb、@djreillo、@dlehmhus、@doinki、@dpnolte、@Drblessing、@dtinth、@ducanhgh、@DuCanhGH、@ductnn、@duncanogle、@dunklesToast、@DustinsCode、@dvakatsiienko、@dvoytenko、@dylanjha、@ecklf、@EndangeredMassa、@eps1lon、@ericfennis、@escwxyz、@Ethan-Arrowood、@ethanmick、@ethomson、@fantaasm、@feikerwu、@ferdingler、@FernandVEYRIER、@feugy、@fgiuliani、@fomichroman、@Fonger、@ForsakenHarmony、@franktronics、@FSaldanha、@fsansalvadore、@furkanmavili、@g12i、@gabschne、@gaojude、@gdborton、@gergelyke、@gfgabrielfranca、@gidgudgod、@Gladowar、@Gnadhi、@gnoff、@goguda、@greatSumini、@gruz0、@Guilleo03、@gustavostz、@hanneslund、@HarshaVardhanReddyDuvvuru、@haschikeks、@Heidar-An、@heyitsuzair、@hiddenest、@hiro0218、@hotters、@hsrvms、@hu0p、@hughlilly、@HurSungYun、@hustLer2k、@iamarpitpatidar、@ianldgs、@ianmacartney、@iaurg、@ibash、@ibrahemid、@idoob、@iiegor、@ikryvorotenko、@imranbarbhuiya、@ingovals、@inokawa、@insik-han、@isaackatayev、@ishaqibrahimbot、@ismaelrumzan、@itsmingjie、@ivanhofer、@IvanKiral、@jacobsfletch、@jakemstar、@jamespearson、@JanCizmar、@janicklas-ralph、@jankaifer、@JanKaifer、@jantimon、@jaredpalmer、@javivelasco、@jayair、@jaykch、@Jeffrey-Zutt、@jenewland1999、@jeremydouglas、@JesseKoldewijn、@jessewarren-aa、@jimcresswell、@jiwooIncludeJeong、@jocarrd、@joefreeman、@JohnAdib、@JohnAlbin、@JohnDaly、@johnnyomair、@johnta0、@joliss、@jomeswang、@joostdecock、@Josehower、@josephcsoti、@josh、@joshuabaker、@JoshuaKGoldberg、@joshuaslate、@joulev、@jsteele-stripe、@JTaylor0196、@JuanM04、@jueungrace、@juliusmarminge、@Juneezee、@Just-Moh-it、@juzhiyuan、@jyunhanlin、@kaguya3222、@karlhorky、@kevinmitch14、@keyz、@kijikunnn、@kikobeats、@Kikobeats、@kleintorres、@koba04、@koenpunt、@koltong、@konomae、@kosai106、@krmeda、@kvnang、@kwonoj、@ky1ejs、@kylemcd、@labyrinthitis、@lachlanjc、@lacymorrow、@laityned、@Lantianyou、@leerob、@leodr、@leoortizz、@li-jia-nan、@loettz、@lorenzobloedow、@lubakravche、@lucasassisrosa、@lucasconstantino、@lucgagan、@LukeSchlangen、@LuudJanssen、@lycuid、@M3kH、@m7yue、@manovotny、@maranomynet、@marcus-rise、@MarDi66、@MarkAtOmniux、@martin-wahlberg、@masnormen、@matepapp、@matthew-heath、@mattpr、@maxleiter、@MaxLeiter、@maxproske、@meenie、@meesvandongen、@mhmdrioaf、@michaeloliverx、@mike-plummer、@MiLk、@milovangudelj、@Mingyu-Song、@mirismaili、@mkcy3、@mknichel、@mltsy、@mmaaaaz、@mnajdova、@moetazaneta、@mohanraj-r、@molebox、@morganfeeney、@motopods、@mPaella、@mrkldshv、@mrxbox98、@nabsul、@nathanhammond、@nbouvrette、@nekochantaiwan、@nfinished、@Nick-Mazuk、@nickmccurdy、@niedziolkamichal、@niko20、@nikolovlazar、@nivak-monarch、@nk980113、@nnnnoel、@nocell、@notrab、@nroland013、@nuta、@nutlope、@obusk、@okcoker、@oliviertassinari、@omarhoumz、@opnay、@orionmiz、@ossan-engineer、@patrick91、@pauek、@peraltafederico、@Phiction、@pn-code、@pyjun01、@pythagoras-yamamoto、@qrohlf、@raisedadead、@reconbot、@reshmi-sriram、@reyrodrigez、@ricardofiorani、@rightones、@riqwan、@rishabhpoddar、@rjsdnql123、@rodrigofeijao、@runjuu、@Ryan-Dia、@ryo-manba、@s0h311、@sagarpreet-xflowpay、@sairajchouhan、@samdenty、@samsisle、@sanjaiyan-dev、@saseungmin、@SCG82、@schehata、@Schniz、@sepiropht、@serkanbektas、@sferadev、@ShaunFerris、@shivanshubisht、@shozibabbas、@silvioprog、@simonswiss、@simPod、@sivtu、@SleeplessOne1917、@smaeda-ks、@sonam-serchan、@SonMooSans、@soonoo、@sophiebits、@souporserious、@sp00ls、@sqve、@sreetamdas、@stafyniaksacha、@starunaway、@steebchen、@stefanprobst、@steppefox、@steven-tey、@suhaotian、@sukkaw、@SukkaW、@superbahbi、@SuttonJack、@svarunid、@swaminator、@swarnava、@syedtaqi95、@taep96、@taylorbryant、@teobler、@Terro216、@theevilhead、@thepatrick00、@therealrinku、@thomasballinger、@thorwebdev、@tibi1220、@tim-hanssen、@timeyoutakeit、@tka5、@tknickman、@tomryanx、@trigaten、@tristndev、@tunamagur0、@tvthatsme、@tyhopp、@tyler-lutz、@UnknownMonk、@v1k1、@valentincostam、@valentinh、@valentinpolitov、@vamcs、@vasucp1207、@vicsantizo、@vinaykulk621、@vincenthongzy、@visshaljagtap、@vladikoff、@wherehows、@WhoAmIRUS、@WilderDev、@Willem-Jaap、@williamli、@wiredacorn、@wiscaksono、@wojtekolek、@ws-jm、@wxh06、@wyattfry、@wyattjoh、@xiaolou86、@y-tsubuku、@yagogmaisp、@yangshun、@yasath、@Yash-Singh1、@yigithanyucedag、@ykzts、@Yovach、@yutsuten、@yyuemii、@zek、@zekicaneksi、@zignis 和 @zlrlyy