Back返回部落格

Next.js 10

Next.js 10 帶來了內建圖片優化、國際化路由、Next.js 分析工具、React 17 支援等多項新功能!

我們很榮幸推出 Next.js 10,主要功能包含:

內建圖片元件與自動圖片優化

Next.js 的目標是改善兩件事:開發者體驗和使用者體驗。

今年我們已在這兩方面投入大量資源,同時也提升了所有 Next.js 應用程式的效能。我們專注於減少瀏覽器需要載入的 JavaScript 量。

我們推出了超過 20 項新功能 來提升效能和開發者體驗。與此同時,Next.js 核心的 JavaScript 體積已 減少 16%

一月時,我們與 Google Chrome 團隊合作,推出了業界頂尖的 JavaScript 程式碼分割策略。

例如,Barnebys 的應用程式體積 減少了 23%,而 Sumup 的最大 JavaScript 套件體積 減少了 70%。這些改進都是在 無需變更任何程式碼 的情況下實現的。

企業只需將 Next.js 升級至最新版本,即可自動採用這項新策略。

網路上的圖片

雖然我們減少瀏覽器載入 JavaScript 量的努力已見成效,但網路不僅僅是 JavaScript:還包含標記語言和圖片。

圖片佔據了網頁總位元組數的 50%。

圖片對最大內容繪製 (Largest Contentful Paint) 有重大影響,因為它們通常是頁面載入時最大的可見元素。最大內容繪製是 Google 即將用於搜尋排名的一項 核心網頁指標

半數圖片的尺寸超過 1MB,這意味著它們未針對網路顯示進行優化。

現今使用者透過手機、平板和筆電瀏覽網路,但圖片仍採用一刀切的方式。例如:網站載入 2000x2000 像素的圖片,但手機僅以 100x100 像素顯示。

此外,30% 的網頁圖片位於初始視窗外,這意味著瀏覽器載入了使用者需要向下滾動才能看到的圖片。

圖片通常沒有 widthheight 屬性,導致頁面載入時圖片位置跳動。這會影響累計版面位移 (Cumulative Layout Shift) 這項核心網頁指標。

99.7% 的網站圖片未使用 WebP 等現代圖片格式。

要在網頁上高效使用圖片,需考慮許多面向:尺寸、重量、延遲載入和現代圖片格式。

開發者需要設定複雜的建置工具來優化圖片,但這些工具通常無法處理來自外部資料源的使用者上傳圖片,導致無法優化所有圖片。

這項不可能的開發任務最終導致終端使用者體驗不佳。

Next.js 圖片元件

我們很高興宣布針對網路高效圖片的解決方案:Next.js 圖片元件與自動圖片優化。

最基本的 Next.js 圖片元件只是 HTML <img> 元素的替代品,專為現代網路進化而來。

<img
  src="/profile-picture.jpg"
  width="400"
  height="400"
  alt="Profile Picture"
/>
import Image from 'next/image';
<Image
  src="/profile-picture.jpg"
  width="400"
  height="400"
  alt="Profile Picture"
/>;

Google Chrome 團隊協助創建了這個 React 元件,透過將最佳實踐設為預設值來提升頁面效能。

使用 next/image 元件時,圖片會自動延遲載入,這意味著它們僅在使用者即將看到時才會渲染。這避免了載入那 30% 位於初始視窗外的圖片。

圖片尺寸會被強制執行,讓瀏覽器能立即渲染圖片所需的空間,而不是在載入時突然出現,防止版面位移。

雖然 HTML <img> 元素上的 widthheight 可能導致響應式版面問題,但 使用 next/image 時不會發生這種情況。使用 next/image 時,圖片會根據提供的 widthheight 自動實現響應式調整。

開發者可標記位於初始視窗內的圖片,讓 Next.js 自動預載這些圖片。預載初始視窗內的圖片已顯示可將最大內容繪製提升達 50%。

自動圖片優化

即使與 HTML <img> 元素相比有這些改進,仍存在一個主要問題。2000x2000 像素的圖片會被傳送至僅渲染較小圖片的手機。

Next.js 10 也解決了這個問題。next/image 元件將透過內建圖片優化自動生成較小尺寸。

內建圖片優化會自動以 WebP 等現代圖片格式提供圖片(如果瀏覽器支援),這比 JPEG 小約 30%。它也允許 Next.js 自動採用 未來 的圖片格式,並將其提供給支援這些格式的瀏覽器。

圖片優化適用於任何圖片來源。即使圖片來自外部資料源(如 CMS),它們也會被優化。

Next.js 10 不是在建置時優化圖片,而是在使用者請求時按需優化。與靜態網站生成器和僅靜態解決方案不同,無論是發佈 10 張還是 1000 萬張圖片,建置時間都不會增加。

結論

新的 next/image 元件和自動圖片優化是強大的新功能,將大幅提升使用者體驗。

next/image 元件處理自動延遲載入、關鍵圖片預載、跨裝置正確尺寸調整,並自動支援現代格式。這些功能適用於任何來源的圖片。

我們期待看到這些新功能如何讓您的使用者體驗變得更快。

更多詳細資訊,請查看 Next.js 圖片元件與自動圖片優化文件

國際化路由

今年,多家企業和社群成員幫助我們團隊理解國際化的重要性。

例如,我們了解到 72% 的消費者更可能停留在翻譯過的網站上,而 55% 的消費者表示他們只從使用母語的電商網站購買。

如果您計劃進入不同國家的市場,專案的國際化對成功至關重要。

專案國際化有兩大支柱:翻譯和路由。

許多 React 函式庫準備了應用程式以進行翻譯,但大多數期望您手動處理路由,且通常僅適用於一種渲染策略。

這就是為什麼作為 Next.js 10 的一部分,我們發布了對國際化路由和語言檢測的內建支援。

這種對國際化路由的內建支援適用於 Next.js 的混合策略,因此您可以按頁面選擇靜態生成或伺服器渲染。

Next.js 10 支援兩種最常見的路由策略:子路徑路由和網域路由。

對於這兩種策略,您首先需要在 Next.js 配置中設定語言環境。

next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'nl'],
    defaultLocale: 'en',
  },
};

語言環境是 UTS 語言環境識別碼,一種定義語言環境的標準化格式。

通常語言環境識別碼由語言、地區和文字組成,以連字號分隔:語言-地區-文字。地區和文字是可選的。例如:

  • en-US - 美國使用的英語
  • nl-NL - 荷蘭使用的荷蘭語
  • nl - 荷蘭語,無特定地區

配置語言環境後,您可以選擇子路徑或網域路由。

子路徑路由

子路徑路由將語言環境放在網址中。這允許所有語言存在於單一網域上。

例如,您可以將語言環境插入網址,如 /nl-nl/blog/en/blog

網域路由

網域路由允許您將語言環境映射至頂級網域。例如 example.nl 可映射至 nl 語言環境,而 example.com 可映射至 en 語言環境。

網域路由需要一些額外配置來了解如何路由網域:

next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'nl'],
    domains: [
      {
        domain: 'example.com',
        defaultLocale: 'en',
      },
      {
        domain: 'example.nl',
        defaultLocale: 'nl',
      },
    ],
  },
};

語言檢測

Next.js 10 在 / 路由上基於 Accept-Language 標頭提供內建語言檢測,所有現代瀏覽器都支援此標頭。配置的語言環境將與 Accept-Language 標頭匹配,然後根據配置的策略進行重定向。

搜尋引擎優化

由於 Next.js 知道使用者訪問的頁面語言,它會自動將 lang 屬性添加到 <html> 標籤。

Next.js 不知道頁面的變體,因此需要您使用 next/head 添加 hreflang 元標籤。您可以在 Google 網站管理員文件 中了解更多關於 hreflang 的資訊。

Next.js 國際化的未來

國際化路由是使專案國際化和本地化更簡單的一系列功能中的第一個。國際化路由允許與大多數 React 國際化函式庫整合。

要了解更多關於國際化路由的資訊,請查看 國際化路由文件

Next.js 速度洞察

在 Vercel,我們知道無法修正無法測量的問題。

您的訪客對網站效能越來越敏感。超過 50% 的訪客 如果載入時間超過 3 秒 就會放棄您的網站。如果您從事電商,許多人發現將載入時間縮短 1/10 秒可導致 轉換率提高 1%

由於效能對您的成功至關重要,我們很自豪地發布 Next.js 速度洞察。這是追蹤真實世界效能指標並將這些洞察回饋至開發流程的解決方案。

使用 Next.js 速度洞察:

不再只測量一次,現在您可以持續測量。

不再只在開發裝置上測量,測量將來自訪客實際使用的裝置。

Next.js 速度洞察著眼於整體情況,深入了解您的受眾以及應用程式對使用者的表現。

我們如此堅持收集真實數據,是因為效能不佳的原因並不總是最明顯的。效能退步可能來自多種因素——第三方腳本和樣式表,或過大或緩慢的第一方字體、圖片和影片。

核心網頁指標 (Core Web Vitals)

Google 與 網頁效能工作小組 (Web Performance Working Group) 共同制定了一套指標,用於準確衡量使用者體驗網站效能的方式,這些指標被恰當地命名為「核心網頁指標 (Web Vitals)」。核心網頁指標追蹤的是網站感知載入速度、互動反應性與視覺穩定性——這三者對網站的整體健康狀態至關重要!

感知載入速度可以透過最大內容繪製 (Largest Contentful Paint, LCP) 來衡量,也就是頁面所有內容顯示完成的時間。舉例來說,當我開啟一個購買運動鞋的連結時,從點擊連結到看見運動鞋圖片、價格以及加入購物車按鈕所花費的時間就是 LCP。

頁面互動反應性則可以透過首次輸入延遲 (First Input Delay, FID) 來衡量,它測量的是使用者首次與頁面互動後,需要等待多久才能看到反應。例如,從我點擊「加入購物車」到購物車數量增加的這段時間就是 FID。

最後,視覺穩定性可以透過累計版面位移 (Cumulative Layout Shift, CLS) 來衡量,也就是元素在顯示給使用者後移動的程度。例如,我們都曾遇過想點擊按鈕時,卻因為圖片載入過慢導致按鈕位移的惱人情況——這就是版面位移。

持續測量並確保這些核心網頁指標符合使用者實際體驗至關重要。這是唯一能真正了解網站對使用者表現如何的方式。網站的效能會因使用者的裝置、網路條件或互動方式而有顯著差異。載入個人化內容或廣告的網站,其效能表現也可能因使用者而大不相同。

模擬測試無法捕捉這些重要訊號。

Next.js Speed Insights 讓您能捕捉真實世界的洞察,而非合成基準測試。它提供持續的測量數據流,而非依賴偶爾的測試,確保這成為您開發工作流程的一部分。

Next.js Speed Insights 讓您能捕捉 真實世界的洞察,而非合成基準測試。它提供 持續的數據流 進行測量,而非依賴偶爾的測試,確保這成為您開發工作流程的一部分

立即前往 nextjs.org/analytics 了解如何在您的應用程式中啟用此功能。

Next.js Commerce

電子商務是網路最重要的用途之一。Next.js 10 的新功能為電子商務提供了強大的新工具。

因此,我們今天與 BigCommerce 合作發布了 Next.js Commerce,這是一套適用於電子商務網站的 All-in-One React 入門套件。Next.js 開發者只需點擊幾下即可克隆、部署並完全自訂它。立即開始使用 nextjs.org/commerce

React 17 支援

React 17 對 Next.js 沒有重大變更,但需要進行一些維護性調整,例如更新 peer dependencies。當使用 React 17 時,新的 JSX 轉換 會自動啟用,無需變更任何配置。

要開始使用 React 17,您只需升級 Next.js 和 React:

Terminal
npm install next@latest react@latest react-dom@latest

getStaticProps / getServerSideProps 快速重新整理 (Fast Refresh)

現在,當您編輯 getStaticPropsgetServerSideProps 函數時,Next.js 會自動重新執行該函數並套用新數據。這讓您能更快地進行迭代,而無需重新整理頁面。

要了解更多關於 getStaticPropsgetServerSideProps 的資訊,您可以閱讀 資料獲取文件

MDX 的快速重新整理 (Fast Refresh)

當透過 @next/mdx 在 Next.js 中使用 MDX 時,現在變更 MDX 內容會觸發快速重新整理,確保瀏覽器在編輯時無需重新載入頁面。

@next/mdx 文件 會引導您如何在 Next.js 中設定 MDX。

從第三方 React 元件匯入 CSS

您現在可以在 React 元件內部匯入第三方 CSS。這允許僅針對單一元件的程式碼分割 CSS。例如,您現在可以使用 react-datepicker 函式庫,而無需在 _app.js 中匯入 CSS:

components/MyComponent.js
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
 
function MyComponent() {}

您可以參考 內建 CSS 支援文件 以了解更多關於 Next.js 如何處理 CSS 匯入的資訊。

自動解析 href

如果您之前使用過動態路由,可能曾遇過需要同時為 next/link 提供 hrefas 屬性的情況。它看起來會像這樣:

<Link href="/categories/[slug]" as="/categories/books" />

這讓 Next.js 能為動態參數插值 href,但當開發者忘記添加 as 或將 as 錯誤地放在 href 中時,會導致頁面轉換不使用客戶端路由,造成不便。

幾個月前,我們著手解決這個開發者痛點,主要目標是改善開發者體驗和終端使用者體驗。我們逐步實現了一個解決方案,允許自動解析 href

我們很高興宣布,作為 Next.js 10 的一部分,在多數使用情境下您不再需要使用 as 屬性。這減少了開發者的不便,同時提升了終端使用者體驗。

此變更完全向後兼容,如果您目前同時使用 hrefas,現有行為將保持不變。

要採用自動 href 解析功能,您只需變更 next/link 的使用方式,僅使用 href 並填入原本放在 as 屬性中的值即可。

<Link href="/categories/books" />

要了解更多關於 next/link 和客戶端路由的資訊,您可以參考 next/link 文件

@next/codemod CLI

我們致力於透過廣泛的向後兼容性,確保 Next.js 升級過程盡可能順利。這項承諾始於極少地棄用功能,同時引入新的更好的解決方案。在此基礎上,我們對所有 Next.js 功能進行了廣泛的整合測試,包括複製本地開發環境的測試。

當 Next.js 中的某個功能被棄用並需要大規模程式碼變更時,我們的團隊會為其建立一個 codemod。Codemod 是一種自動化的程式碼轉換工具,您可以對專案執行以更新原始碼。

例如:我們發布了一個將箭頭函數和匿名函數轉換為命名函數的 codemod。此轉換 是必要的,否則 React 快速重新整理 (Fast Refresh) 無法將該函數識別為有效的 React 元件。同樣地,React hooks ESLint 規則也無法將該函數識別為 React 元件。

隨著 Next.js 10 的發布,我們推出了一個新的 Next.js codemods CLI 工具,讓您只需執行單一指令即可更新應用程式:npx @next/codemod <transform> <path>

要了解更多關於 codemods 的資訊,您可以查看 Next.js Codemods 文件

getStaticPaths 的阻塞回退 (Blocking Fallback)

在 Next.js 9.3 中,我們引入了 getStaticPropsgetStaticPaths,以及能在 getStaticPaths 中返回 fallback 屬性的功能。fallback 屬性允許生成額外的靜態頁面而無需完整重建,最初會提供一個靜態 HTML 檔案,然後在後續請求中被完全渲染的內容取代。過去幾個月,我們收到許多公司的反饋,他們希望有類似但略有不同的行為:當使用者首次請求頁面時進行阻塞預渲染 (blocking pre-render)。在首次渲染後,該頁面將被快取供後續請求使用。

Next.js 10 解決了這個需求。

我們很高興宣布 getStaticPaths 的新模式 fallback: 'blocking',它啟用了阻塞行為,不會向瀏覽器發送靜態回退。相反地,初始請求會等待預渲染完成。

pages/posts/[id].js
export function getStaticPaths() {
  return {
    // 為回退行為啟用阻塞模式
    fallback: 'blocking',
  };
}

要了解更多關於增量生成額外靜態頁面的 fallback 行為,您可以參考 fallback 文件

getStaticProps / getServerSideProps 的重新導向 (Redirect) 與 404 (notFound) 支援

自從引入 getStaticPropsgetServerSideProps 以來,我們注意到有些情況下使用者需要返回重新導向和 404 回應。為了簡化這些情況,我們現在允許從 getStaticPropsgetServerSideProps 返回兩個新欄位:notFoundredirect

notFound 支援

當返回 notFound 欄位並設為 true 時,將返回預設的 404 頁面,狀態碼為 404。這讓您能避免在 SSG 中生成額外頁面,也無需手動處理 404 頁面的渲染。

pages/posts/[id].js
export function getStaticProps() {
  return {
    // 返回預設 404 頁面,狀態碼為 404
    notFound: true,
  };
}

redirect 支援

現在可以返回重新導向,其中包含 destination 以及指示是否為永久重新導向的 permanent 欄位(例如 permanent: true)。對於需要使用特定狀態碼而非預設值的情況,也可以返回可選的 statusCode 欄位來替代 permanent

pages/posts/[id].js
export function getStaticProps() {
  return {
    // 重新導向至內部頁面 `/another-page`
    redirect: {
      destination: '/another-page',
      permanent: false,
    },
  };
}
pages/posts/[id].js
export function getServerSideProps() {
  return {
    // 重新導向至外部網域 `example.com`
    redirect: {
      destination: 'https://example.com',
      permanent: false,
    },
  };
}

結語

我們很高興看到 Next.js 的採用持續增長:

  • 我們已有超過 1,300 位獨立貢獻者,自 9.5 版發布以來新增了超過 120 位新貢獻者
  • 在 GitHub 上,該專案已獲得超過 54,800 次星標

加入 Next.js 社群 GitHub Discussions。Discussions 是一個社群空間,讓您能與其他 Next.js 使用者聯繫,自由提問或分享您的工作。

致謝

我們感謝我們的社群,包括所有幫助塑造此版本的外部反饋與貢獻。

此版本由以下貢獻者共同實現:@ijjk, @adebiyial, @elliottsj, @saintmalik, @HaNdTriX, @prateekbh, @amirsaeed671, @paambaati, @imagentleman, @gregrickaby, @Janpot, @atcastle, @Kirkhammetz, @remorses, @davidsonsns, @kmkzt, @slawekkolodziej, @Timer, @styfle, @timneutkens, @ykzts, @ashconnell, @orYoffe, @lfades, @justinwhall, @fbaiodias, @ludofischer, @felipeguilhermefs, @gr-qft, @TasukuUno, @YichiZ, @weichienhung, @seosmmbusiness, @HsuTing, @gsimone, @peduarte, @ztanner, @neighborhood999, @chibicode, @merceyz, @opudalo, @lunchboxav, @mohsen1, @akd-io, @justman00, @helloworld, @devknoll, @borekb, @ArthurMaverick, @sakito21, @TrySound, @omBratteng, @svenheden, @hallaji, @kettanaito, @vvo, @m-lautenbach, @jensmeindertsma, @Zeko369, @longlho, @stefanprobst, @laugharn, @sdornan, @daneroo, @mohd-akram, @austingmhuang, @sphilee, @devinekadeni, @Bacher, @nghiepit, @tomasdisk, @leader22, @paulogdm, @284km, @belgattitude, @geritol, @stigkj, @sampoder, @samrobbins85, @Pitasi, @digitalPlayer1125, @timfee, @plug-n-play, @philihp, @leerob, @dylanjha, @Kerumen, @rdimaio, @jorisw, @zerbinidamata, @jamesgeorge007, @Jashnm, 以及 @futantan!