首頁 > web前端 > js教程 > 主體

Next.js v—反思錯誤

Mary-Kate Olsen
發布: 2024-10-26 04:06:02
原創
934 人瀏覽過

你好!這是另一篇關於 next.js 的文章。最後,關於新版本!每個版本都包含一組新的、有趣的和有爭議的功能。這個版本也不例外。然而,新版本的有趣之處並不在於它的新功能,而是在於 next.js 中優先順序和組織的變化。是的,正如您可能從標題中猜到的那樣,此版本的重要部分對於反思先前的錯誤很有價值。

從版本 8 左右開始,我就一直在使用 next.js。一直以來,我一直饒有興趣地關注它的開發(有時並非沒有失望)。最近,我發表了一系列關於與新的App Router 作鬥爭的文章- “Next.js App Router。通往未來的道路還是錯誤的轉折”、“Next.js 緩存。禮物還是詛咒”、“為圖書館之神提供更多圖書館或我如何重新思考i18n」。所有這些都是 next.js 之前版本的思想和功能開發非常薄弱的​​結果。正因為如此,我對新版的興趣有增無減。除此之外,人們也渴望了解框架中的變化向量。

在本文中,我不會詳細討論 App Router 或伺服器元件是什麼 - 這些在之前的文章中有詳細描述。我們將只關注新版本和新變化。

註:文章反映了從作者角度來看最有趣的變化。它們與官方清單不同,因為作者是從框架中的提交和 PR 中選擇它們的。

Next.js v15 發布

首先,介紹一下 next.js 內部開發流程的變更。框架團隊首次發布了候選版本(RC 版本)。顯然,他們這樣做是因為 React.js 團隊決定發布 React v19 RC。

通常,穩定版本中的 next.js 團隊會平靜地使用「Canary」版本分支中的 React(該分支被認為是穩定的,建議框架使用)。然而,這一次,他們決定採取不同的做法(劇透 - 沒有白費)。

兩個團隊的計劃都很簡單 - 發布預發布版本,讓社區檢查問題,然後在幾週內發布完整版本。

Next.js v— Reflecting on Mistakes


來自 React.js 核心團隊開發人員的推文 https://x.com/acdlite/status/1797668537349328923

React.js 的候選版本發布已經過去了 6 個多月,但穩定版本仍未發布。 React.js 穩定版本的延遲發布也影響了 next.js 的計畫。因此,與傳統相反,他們在第 15 個版本已經開始工作的同時,總共發布了 15 個附加補丁版本(通常是 3-5 個補丁,然後發布一個版本)。這裡值得注意的是,這些修補程式版本並沒有包含所有累積的更改,而只是解決了關鍵問題,這也偏離了 next.js 的常規流程。

next.js 中的基本發布流程是,所有內容都合併到金絲雀分支中,然後在某個時刻,該分支作為穩定版本發布。

然而,因此,next.js 團隊決定與 React.js 版本解耦,在 React.js 穩定版本發布之前發布穩定版本的框架。

文件版本控制

另一個非常有用的組織變革。最後,可以查看不同版本的文件。這就是為什麼這麼重要:

首先,由於重大變化,更新 next.js 通常是一項相當具有挑戰性的任務。事實上,這就是為什麼版本 12 的下載量仍然超過 200 萬次,版本 13 的下載量每月超過 400 萬次(公平地說,版本 14 的下載量超過 2000 萬次)。

因此,先前版本的使用者需要特定於其版本的文檔,因為新版本可能會重寫一半。

Next.js v— Reflecting on Mistakes


Next.js 文件版本控制 - nextjs.org/docs

另一個問題是 Next.js 本質上使用單一通道。文件也對其進行了更改。因此,金絲雀版本的變更描述立即出現在主要文件中。現在它們顯示在“金絲雀”部分下。

使用反應

一開始,我提到 Next.js 目前正在使用 React.js 的 RC 版本。但事實上,這並不完全正確,或說不完全正確。事實上,Next.js 目前使用兩種 React.js 設定:App Router 的第 19 個金絲雀版本和 Pages Router 的第 18 個版本。

有趣的是,有一次他們也想包含 Pages Router 的第 19 版,但後來又回滾了這些變更。現在,在穩定版本發布後,承諾全面支援 React.js 版本 19。

除此之外,新版本還將對伺服器操作功能進行一些有用的改進(是的,React團隊將它們重命名為):

  • 重量和性能最佳化;
  • 改進的錯誤處理;
  • 修正了伺服器功能的重新驗證和重定向。

我想我也會在本節中包含 Next.js 的新功能 - Form 元件。總的來說,它是 React-dom 中熟悉的形式,但有一些改進。如果成功提交表單涉及導航到另一個頁面,則主要需要此元件。對於下一頁,將預先載入loading.tsx和layout.tsx抽象。

import Form from 'next/form'

export default function Page() {
  return (
    <Form action="/search">;
      {/* On submission, the input value will be appended to 
          the URL, e.g. /search?query=abc */}
      <input name="query" />;
      <button type="submit">Submit</button>;
    </Form>;
  )
}
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

開發者體驗 (DX)

在談論 Next.js 時,我們不能忽視開發者體驗。除了「更快、更高、更強」標準(我們稍後也會討論)之外,還發布了一些有用的改進。

期待已久的對最新 ESLint 的支援。 Next.js 到目前為止還不支援 ESLint v9。儘管 eslint 本身 (v8) 及其一些子依賴項已被標記為已棄用,但情況仍然如此。這導致了一種不愉快的情況,項目基本上被迫保留已棄用的包。

錯誤介面略有改進(在 Next.js 中已經清晰方便):

  • 新增了複製堆疊追蹤的按鈕;
  • 新增了在編輯器中的特定行開啟錯誤來源的功能。

Next.js v— Reflecting on Mistakes


在 next.js 複製錯誤堆疊的範例

新增了「靜態指示器」 - 頁面一角的一個元素,顯示頁面已在靜態模式下建置。
總的來說,這是一件小事,但有趣的是他們將其作為新的東西包含在關鍵更改中。 「預建」頁面的指示器大約從版本 8 (2019) 開始就已經存在,本質上,他們只是稍微更新了它並針對 App Router 進行了調整。

Next.js v— Reflecting on Mistakes

也新增了包含偵錯資訊的目錄 - .next/diagnostics。它將包含有關建置過程和發生的所有錯誤的資訊。目前尚不清楚這在日常使用中是否有用,但在解決 Vercel devrel 問題時肯定會使用它(是的,它們有時有助於解決問題)。

Next.js v— Reflecting on Mistakes
Next.js 團隊對 [關於專案建置速度緩慢的推文] 的回應(https://x.com/darshansrc/status/1797339543571755425)

建構過程的變化

討論完 DX,值得談談建造過程。還有 Turbopack。

渦輪機組

以及該領域最大的新聞。 Turbopack 的開發模式現已完全完成! 「Turbopack 100% 的現有測試均通過且沒有錯誤」

現在Turbo團隊正在開發生產版本,逐步進行測試和完善(目前完成約96%)

Next.js v— Reflecting on Mistakes
next.js 中的範例變更日誌部分

Turbopack 也增加了新功能:

  • 使用 Turbopack 設定建構的記憶體限制;
  • Tree Shaking(刪除未使用的程式碼)。
import Form from 'next/form'

export default function Page() {
  return (
    <Form action="/search">;
      {/* On submission, the input value will be appended to 
          the URL, e.g. /search?query=abc */}
      <input name="query" />;
      <button type="submit">Submit</button>;
    </Form>;
  )
}
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

Turbopack 中的這些和其他改進“減少了 25-30% 的內存使用量”,並且“將大量頁面的構建速度加快了 30-50%”。

其他

重大的樣式問題已修復。在版本 14 中,經常會出現導航過程中樣式順序被破壞的情況,導致樣式 A 高於樣式 B,反之亦然。這改變了它們的優先級,因此元素看起來不同。

下一個期待已久的改進。現在可以用 TypeScript 寫設定檔 - next.config.ts

const nextConfig = {
  experimental: {
    turbo: {
      treeShaking: true,
      memoryLimit: 1024 * 1024 * 512 // in bytes / 512MB
    },
  },
}
登入後複製
登入後複製
登入後複製
登入後複製

另一個有趣的更新是重試靜態頁面建置。這意味著如果頁面在建置時失敗(例如,由於網路問題) - 它將嘗試再次建置。

import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  /* config options here */
};

export default nextConfig;
登入後複製
登入後複製
登入後複製
登入後複製

總結本節,這是社區非常期望的功能 - 指定用於構建的其他文件的路徑的能力。例如,使用此選項,您可以指定檔案不位於應用程式目錄中,而是位於 module/main、modules/invoices 等目錄中。

但是,目前他們僅出於團隊內部目的添加它。而在這個版本中,他們肯定不會呈現。展望未來,它將用於滿足 Vercel 需求,或者他們將對其進行測試並在下一個版本中呈現。

框架 API 的變化

Next.js 更新中最痛苦的部分 - API 變更。並且在這個版本中,還有重大更新。

幾個內部框架 API 已變成非同步 - cookies、headers、params 和 searchParams(所謂的動態 API)。

const nextConfig = {
  experimental: {
    staticGenerationRetryCount: 3,
  },
}
登入後複製
登入後複製

這是一個重大變化,但 Next.js 團隊承諾所有這些功能都可以透過呼叫他們的 codemod 來自動更新:

npx @next/codemod@canary next-async-request-api .

另一個變化,但可能與許多人無關。金鑰 geo 和 ip 已從 NextRequest 中刪除(用於中間件和 API 路由)。本質上,此功能僅在 Vercel 中有效,而在其他地方開發人員則制定了自己的方法。對於 Vercel,此功能將移至 @vercel/functions 套件

還有一些更新:

  • 在 revalidateTag 中,您現在可以一次傳遞多個標籤;
  • 鍵 images.remotePatterns.search 和 images.localPatterns 已新增至 next/image 的配置。這些可以更好地控製影像壓縮的位址限制。
import Form from 'next/form'

export default function Page() {
  return (
    <Form action="/search">;
      {/* On submission, the input value will be appended to 
          the URL, e.g. /search?query=abc */}
      <input name="query" />;
      <button type="submit">Submit</button>;
    </Form>;
  )
}
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

快取

在我個人看來,這是 Next.js 最重要的變化發生的地方。最大的消息是 - 現在預設禁用快取我不會詳細討論快取問題,這在「Next.js 快取。禮物還是詛咒」一文中主要介紹了。

讓我們看看快取中的所有主要變化:

  • 具體來說,fetch 現在預設使用 no-store 值而不是強制快取;
  • API 路由現在預設在強制動態模式下工作(之前預設為強制靜態,這表示它們在建置時被編譯為靜態回應[如果頁面上未使用動態API]);
  • 客戶端路由器中的快取也已停用。以前,如果客戶端訪問路由中的頁面 - 它會被緩存在客戶端上並保持該狀態,直到重新載入頁面。現在,每次都會載入目前頁面。可以透過 next.config.js 重新配置此功能:
const nextConfig = {
  experimental: {
    turbo: {
      treeShaking: true,
      memoryLimit: 1024 * 1024 * 512 // in bytes / 512MB
    },
  },
}
登入後複製
登入後複製
登入後複製
登入後複製
  • 此外,即使啟用了客戶端快取 - 它顯然也會在正確的時刻更新。具體來說,如果伺服器上啟用的頁面的快取過期。
  • 伺服器元件現在在開發模式下快取。這使得開發更新發生得更快。只需重新載入頁面即可清除快取。您也可以透過 next.config.js 完全停用此功能:
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  /* config options here */
};

export default nextConfig;
登入後複製
登入後複製
登入後複製
登入後複製
  • 您現在可以管理「Cache-Control」標頭。以前,它總是被 Next.js 的內部值嚴格覆蓋。這導致了透過 CDN 進行快取的工件;
  • next/dynamic 快取模組並重複使用它們,而不是每次都重新載入它們;

這就是關於「歷史誤會」的問題。新的 API 也會出現在 Next.js 中。即所謂的動態I/O。目前還沒有任何相關的文章,所以以下是作者根據改動的猜測。

動態 I/O 似乎是動態建構的高階模式。類似於 PPR(部分預渲染),或者更準確地說,它的補充。簡而言之,部分預渲染是一種頁面構建模式,其中大多數元素在構建時構建並緩存,而單個元素則針對每個請求構建。

因此,動態 I/O [可能] 最終確定了該邏輯的架構。它擴展了快取功能,以便可以根據模式和使用地點精確地啟用和停用它(是否在「動態」區塊中)。

import Form from 'next/form'

export default function Page() {
  return (
    <Form action="/search">;
      {/* On submission, the input value will be appended to 
          the URL, e.g. /search?query=abc */}
      <input name="query" />;
      <button type="submit">Submit</button>;
    </Form>;
  )
}
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

除此之外,還加入了「使用快取」指令。它將在 Nodejs 和邊緣運行時中可用,顯然,在所有伺服器段和抽像中都可用。透過在函數或匯出函數的模組頂部指定此指令 - 其結果將被快取。該指令僅在啟用dynamicIO時才可用。

const nextConfig = {
  experimental: {
    turbo: {
      treeShaking: true,
      memoryLimit: 1024 * 1024 * 512 // in bytes / 512MB
    },
  },
}
登入後複製
登入後複製
登入後複製
登入後複製

另外,專門為了使用緩存,增加了方法cacheLife和cacheTag

import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  /* config options here */
};

export default nextConfig;
登入後複製
登入後複製
登入後複製
登入後複製

cacheTag將用於使用revalidateTag進行重新驗證,cacheLife將設定快取生存期。對於cacheLife 值,您需要使用預設值之一。幾個開箱即用的選項(“秒”,“分鐘”,“小時”,“天”,“週”,“最大”),可以在 next.config.js 中指定其他選項:

const nextConfig = {
  experimental: {
    staticGenerationRetryCount: 3,
  },
}
登入後複製
登入後複製

部分預渲染 (PPR)

可能是下一個版本的主要功能。如前所述,PPR 是一種頁面建立模式,其中大多數元素在建置時組裝並緩存,而單個元素則針對每個請求進行組裝。同時,預先建置的部分會立即傳送到客戶端,而其餘部分則動態載入。

Next.js v— Reflecting on Mistakes


部分預先渲染的工作原理

該功能本身是六個月前在候選版本中作為實驗性 API 引入的。此 API 將保持這種狀態,我們可能只會在版本 16 中看到它穩定(這很好,因為主要功能通常會在六個月到一年內過渡到穩定)。

關於更改。前面說過,主要是更新了工作原理。不過,從使用PPR的角度來看,這幾乎沒有什麼影響。同時,它也獲得了多項改進:

以前,配置中只有一個標誌,但現在要啟用 PPR,您需要指定「增量」。這樣做顯然是為了讓邏輯更加透明 - 即使在 PPR 中,開發者也可以快取內容,並且要更新它,您需要呼叫 revalidate 方法。

import { cookies } from 'next/headers';

export async function AdminPanel() {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');

  // ...
}
登入後複製

另外,之前PPR是針對整個專案啟動的,但現在需要針對每個分段(佈局或頁面)啟用:

const nextConfig = {
  images: {
    localPatterns: [
      {
        pathname: '/assets/images/**',
        search: 'v=1',
      },
    ],
  },
}
登入後複製

另一個變化是部分回退預渲染(PFPR)。正是由於這項改進,預先建置的部分立即發送到客戶端,而其餘部分則動態載入。在此期間,會顯示回呼組件來取代動態元素。

import Form from 'next/form'

export default function Page() {
  return (
    <Form action="/search">;
      {/* On submission, the input value will be appended to 
          the URL, e.g. /search?query=abc */}
      <input name="query" />;
      <button type="submit">Submit</button>;
    </Form>;
  )
}
登入後複製
登入後複製
登入後複製
登入後複製
登入後複製

儀器儀表

Instrumentation 被標記為穩定的 API。檢測檔案允許使用者掛鉤 Next.js 伺服器的生命週期。它適用於整個應用程式(包括 Pages Router 和 App Router 的所有部分)。

目前,instrumentation 支援以下鉤子:

register - 初始化 Next.js 伺服器時呼叫一次。它可用於與可觀測性庫(OpenTelemetry、datadog)整合或用於特定於專案的任務。

onRequestError - 為所有伺服器錯誤呼叫的新掛鉤。它可用於與錯誤追蹤庫(Sentry)整合。

const nextConfig = {
  experimental: {
    turbo: {
      treeShaking: true,
      memoryLimit: 1024 * 1024 * 512 // in bytes / 512MB
    },
  },
}
登入後複製
登入後複製
登入後複製
登入後複製

攔截器

攔截器,也稱為路由級中間件。它類似於一個成熟的[已經存在的]中間件,但與後者不同:

  • 它可以在 Node.js 運行時運行;
  • 它在伺服器上工作(這意味著它可以存取環境和統一快取);
  • 可以多次添加,嵌套繼承(類似於中間件測試版時的工作方式);
  • 它也適用於伺服器功能。

此外,當建立攔截器檔案時,樹中下面的所有頁面都會變成動態的。

import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  /* config options here */
};

export default nextConfig;
登入後複製
登入後複製
登入後複製
登入後複製

說到Vercel,中間件現在將作為CDN 級別的主要簡單檢查而有效(因此,例如,如果請求不被允許,則立即返回重定向),而攔截器將在伺服器,執行全面的檢查和複雜的操作。

然而,在自架中,這樣的分割顯然效率較低(因為兩個抽像都在伺服器上工作)。僅使用攔截器可能就足夠了。

結論

覆蓋提取、激進的快取、大量錯誤以及忽略社區請求。 Next.js 團隊做出了錯誤的決定,倉促發布,並且不顧社群回饋堅持自己的觀點。花了將近一年的時間才認識到這些問題。直到現在,終於,人們感覺到框架再次解決了社區問題。

另一方面,還有其他框架。一年前,在 React.js 演示中,似乎所有框架都將很快與 Next.js 相提並論。 React 開始較少提及 Next.js 作為主要工具,框架展示了即將推出的建置系統、對伺服器元件和功能的支援以及一系列全域變更和整合。時間已經過去了,基本上,他們還沒有達到那個地步。

當然,最終的結論要過一段時間才能得出,但目前看來,React.js 的變化並沒有達到預期的框架水平,反而導致了Next.js 的更大統治地位,框架之間的差異較大(因為伺服器元件和操作的實作由框架自行決定)。

同時,OpenAI 改用 Remix(「因為它有更高的穩定性和便利性」):

Next.js v— Reflecting on Mistakes


在 ChatGPT 重新混合使用

顯然他們在 Next.js 發生重大變化之前就開始了

Next.js v— Reflecting on Mistakes


有關 ChatGPT 從 2024 年 8 月起切換為 Remix 的推文

總的來說,在接下來的 stateofjs 和 stackoverflow 調查中,我們很可能會看到重大的洗牌。

製作人員

程式碼範例或其基礎取自 next.js 文件、提交、PR 和 next.js 核心;

後記

如果您需要一個基於 MD 檔案產生文件的工具 - 請查看 robindoc.com,如果您使用 next.js - 您可能會在 nimpl.tech 的解決方案中找到有用的東西。

以上是Next.js v—反思錯誤的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!