跳至內容
返回部落格

2020 年 5 月 11 日,星期一

Next.js 9.4

發佈者

我們很高興今天推出 Next.js 9.4,其中包含

快速重新整理

快速重新整理是一種全新的熱重載體驗,可讓您即時獲得 React 元件編輯的回饋。現在,Next.js 9.4 或更新版本的專案都預設啟用此功能。

熱重載已經存在很長時間了,但過去以來太過脆弱,無法在您的工作流程中預設啟用。因此,Next.js 先前實作了一種粗略形式的熱重載,會重置整個應用程式的狀態。

舊的熱重載實作無法應對編譯或執行階段錯誤,如果您在編輯 CSS 或 JavaScript 時輸入錯誤,它會執行應用程式的完整重新載入。這並非最佳做法,而且會打斷您的思路。

快速重新整理與 React 本身深度整合(透過 React Refresh),讓 Next.js 可以對 React 元件樹執行可預測的精確更新。

這表示 Next.js 只會更新您編輯的檔案中的程式碼,並且只會重新渲染該元件,而不會遺失元件狀態。這包括樣式(內聯、CSS-in-JS 或 CSS/Sass 模組)、標記、事件處理程式和效果(透過 useEffect)。

一個編輯會話,其中包含編譯器和執行階段錯誤(可快速恢復),以及保留狀態的編輯。

作為此體驗的一部分,我們完全重新設計了錯誤覆蓋,使其更有幫助,並使您的應用程式能夠應對輸入錯誤或執行階段錯誤。這包括但不限於:

  • 精確的錯誤位置,解析至編譯前的程式碼原始行數和欄數
  • 與上下文相關的原始程式碼片段,並可點擊在您的編輯器中開啟
  • 修正語法錯誤後,開發工作階段會繼續而不會遺失應用程式狀態
  • 當您修正錯誤時,未處理的執行階段錯誤會被自動清除

我們要感謝 Dan Abramov 對此功能的寶貴貢獻和協助。

增量靜態再生(測試版)

Next.js 在 9.3 版中引入了靜態網站生成方法,並懷著一個明確的目標:我們應該獲得 靜態的優勢(永遠快速、永遠在線、全球分佈),同時又能保有 Next.js 聞名的出色動態資料支援。

為了兼顧兩者,Next.js 支援增量靜態再生,讓您在建置網站後更新靜態內容。例如,在 9.3 版中,我們在 getStaticPaths 中引入了 fallback: true 選項,讓您可以在執行階段新增新頁面

我們最近整理了一個範例,展示 Next.js 如何以這種方式靜態預渲染無限多個頁面。

今天,我們也推出增量靜態再生(測試版),這是一種更新現有頁面的機制,它會隨著流量的進入在背景重新渲染頁面。受到 stale-while-revalidate 的啟發,這確保了流量服務不會中斷,始終保持靜態,並且新建立的頁面只會在生成完成後才推送。

pages/blog/[slug].js
export async function getStaticProps() {
  return {
    props: await getDataFromCMS(),
    // we will attempt to re-generate the page:
    // - when a request comes in
    // - at most once every second
    unstable_revalidate: 1,
  };
}

與 SSR 不同,增量靜態再生可確保您保留靜態的優勢。

  • 沒有延遲高峰。頁面提供速度始終如一。
  • 頁面永不離線。如果背景頁面重新生成失敗,舊頁面將保持不變。
  • 低資料庫和後端負載。頁面最多同時重新計算一次。

增量功能(新增頁面並延遲更新)以及預覽模式,都已完全受到 next startVercel 邊緣平台 的原生支援。

接下來,我們將致力於補充 RFC,以解決另外兩種增量靜態生成功能。

  • 一次重新產生並失效多個頁面(例如您的部落格索引和特定部落格文章)
  • 透過監聽事件(例如 CMS Webhook)來重新產生,以預先處理使用者流量

CMS 範例

緊接著我們發佈新一代靜態網站產生 (SSG)的公告,我們想分享從 Headless CMS API 擷取內容並將其轉譯為 Next.js HTML 的實際案例。

我們與一些世界頂尖 CMS 系統的創建者合作:ContentfulDatoCMSPrismicSanity 以及 TakeShape,而且還有更多合作正在進行中。

這些範例不僅可以直接使用,而且 100% 開放原始碼並採用 MIT 授權,同時也包含了最佳實務做法。

DatoCMS achieves impeccable results due to their built-in image optimization support.
DatoCMS 因其內建的圖像優化支援,可實現無可挑剔的效果。

DatoCMS 因其內建的圖像優化支援,可實現無可挑剔的效果。

我們也與 TinaCMS 合作,為 CMS 開啟一個令人興奮的新方向:頁面內編輯內容參考他們的指南,了解如何在您的專案中實作。

新增環境變數支援

我們從使用 Next.js 的公司那裡收到的一個常見的意見回饋是,不清楚何時環境變數會被嵌入到瀏覽器套件中,以及何時只能在 Node.js 環境中使用。

今天我們宣布兩個完全向後相容的功能,將有助於簡化這個流程。

首先,您現在可以在環境變數前加上 NEXT_PUBLIC_ 前綴,將其暴露給瀏覽器。當使用該環境變數時,它將會被嵌入到瀏覽器的 JavaScript 套件中。

您不再需要新增 next.config.js 並新增 env 鍵來暴露這些變數。

pages/index.js
// The environment variable will be exposed to the browser
console.log('My Application Version', process.env.NEXT_PUBLIC_VERSION);
 
export default function HomePage() {
  return <h1>Hello World</h1>;
}

第二個變更是 Next.js 現在預設支援 .env 載入。讓您可以輕鬆定義開發和生產環境變數。

您可以在環境變數文件中閱讀更多關於 .env 載入的資訊。

這些新功能將透過遵循以下慣例來簡化環境變數的使用

  • 預設情況下,環境變數僅在 Node.js 環境中可用
  • NEXT_PUBLIC_ 為前綴的環境變數會暴露給瀏覽器

改進的內建 Fetch 支援

Next.js 9.1.7 中,我們宣布了在瀏覽器中對 fetch() API 的 polyfill。現在,這個 polyfill 也擴展到 Node.js 環境了。

實際上,您不再需要使用任何類型的伺服器端 fetch polyfill(例如 isomorphic-unfetchnode-fetch),因為 Next.js 將在所有環境中自動提供 fetch()

例如,當使用在建置時由 Next.js 執行的 getStaticProps

pages/blog.js
export async function getStaticProps() {
  // fetch no longer needs to be imported from isomorphic-unfetch
  const res = await fetch('https://.../posts');
  const posts = await res.json();
 
  return {
    props: {
      posts,
    },
  };
}
 
function Blog({ posts }) {
  // Render posts...
}
 
export default Blog;

整合式網頁效能指標報告

上週,Google Chrome 團隊推出了核心網頁效能指標 (Core Web Vitals)。核心網頁效能指標是提供絕佳網頁使用者體驗的關鍵品質訊號,而知名的Lighthouse 報告也是以此為基礎建構的。

如果您希望您的網站或網路應用程式盡可能快速(這也是 Next.js 的核心目標之一),那麼持續追蹤這些指標將非常有用。

Chrome 團隊已發布核心網頁效能指標 Chrome 擴充功能,讓開發者可以獲得視覺化的回饋,了解網頁的效能表現。

在建構正式版網路應用程式時,您也需要知道網站對於訪客和(潛在)客戶的效能表現。您甚至可能希望追蹤這些指標隨著時間的改善或退步情況,以了解您的變更是否對您的受眾產生預期的影響。

為了協助將核心網頁效能指標報告傳送到您的分析服務,我們與 Google 合作推出了一個名為 reportWebVitals 的新方法,可以從 pages/_app.js 匯出。

pages/_app.js
// Will be called once for every metric that has to be reported.
export function reportWebVitals(metric) {
  // These metrics can be sent to any analytics service
  console.log(metric);
}
 
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}
 
export default MyApp;

要將此方法與您的分析服務搭配使用,請參閱文件中的「將結果傳送到分析服務」一節。如果您想進一步了解核心網頁效能指標,可以參考web.dev/vitals

絕對匯入和別名

如果您正在開發一個大型專案,您的一些 import 陳述式可能會受到 ../../../ 這種義大利麵程式碼的困擾

import Button from '../../../../components/button';

在這種情況下,我們可能會想要使用絕對導入而不是相對導入。假設 `components` 目錄存在於根目錄,我們可能希望 `import` 陳述式看起來像這樣:

import Button from 'components/button';

我們很興奮地宣布 Next.js 9.4 讓 JavaScript 和 TypeScript 專案設定絕對導入變得超級簡單。您只需要將 `baseUrl` 設定加入到 `jsconfig.json` (JS 專案)`tsconfig.json` (TS 專案)

jsconfig.json / tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "."
  }
}

這將允許從 `.`(根目錄)進行絕對導入。它也與 VSCode 和其他編輯器整合,支援程式碼導覽和其他編輯器功能。

注意:如果您先前修改了您的 Webpack 模組別名設定 以啟用絕對導入,現在可以移除該設定。

此外,Next.js 9.4 也支援 `paths` 選項,它允許您建立自訂模組別名。例如,以下設定允許您使用 `@/design-system` 代替 `components/design-system`

jsconfig.json / tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/design-system/*": ["components/design-system/*"]
    }
  }
}

然後您可以像這樣使用您的別名:

// Imports 'components/design-system/button'
import Button from '@/design-system/button';

如果您指定 `paths`,則必須指定 `baseUrl`。您可以在 TypeScript 文件 中了解更多關於 `paths` 選項的資訊。

可設定的 Sass 支援

當內建 Sass 支援在 Next.js 9.3 中推出時,我們收到了一些用戶希望設定 sass 編譯器的回饋。例如設定 `includePaths`。

現在可以透過在 `next.config.js` 中使用 `sassOptions` 鍵來完成此操作。

next.config.js
const path = require('path');
 
module.exports = {
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')],
  },
};

改進的日誌輸出

我們重新設計了命令列輸出,使其更加一致,並減少重複數據的輸出,例如部署網址、等待開發伺服器啟動等等。我們還更改了訊息類型的間距,使其在所有訊息中保持一致,這意味著它們不再從一行跳到另一行。

在 9.4 之前的版本上運行 next dev

在 9.4 上運行 next dev

社群

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

  • 我們已經有超過 1066 位獨立貢獻者。
  • 在 GitHub 上,該專案已被加星標超過 48,000 次。

加入 Next.js 社群,請前往 GitHub 討論區。討論區是一個社群空間,可讓您與其他 Next.js 使用者聯繫並提問。

如果您正在使用 Next.js,歡迎與社群分享您的專案網址

我們感謝我們的社群以及所有幫助塑造此版本發行的外部回饋和貢獻。