Next.js v— 間違いを振り返る

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-10-26 04:06:021000ブラウズ

こんにちは!これは 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 v19 RC を公開するという React.js チームの決定により、これが行われました。

通常、安定版リリースの 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 の基本的なリリース プロセスでは、すべてが Canary ブランチにマージされ、その後、ある時点でこのブランチが安定リリースとして公開されます。

しかし、結果として、next.js チームは React.js リリースから切り離し、React.js の安定版がリリースされる前にフレームワークの安定版を公開することを決定しました。

ドキュメントのバージョン管理

もう 1 つの非常に有益な組織変更です。最後に、ドキュメントのさまざまなバージョンを表示することができます。これが非常に重要な理由は次のとおりです:

まず、next.js の更新は、大きな変更があるため、非常に困難な作業になることがよくあります。実際、これが、依然としてバージョン 12 のダウンロード数が依然として毎月 200 万件を超え、バージョン 13 のダウンロード数が 400 万件を超えている理由です (公平を期すために、バージョン 14 のダウンロード数は 2,000 万件を超えています)。

したがって、新しいバージョンは半分書き直される可能性があるため、以前のバージョンのユーザーはそのバージョンに固有のドキュメントが必要になります。

Next.js v— Reflecting on Mistakes


Next.js ドキュメントのバージョン管理 - nextjs.org/docs

もう 1 つの問題は、Next.js が基本的に単一のチャネルを使用することです。ドキュメントの変更も行われます。したがって、カナリア バージョンからの変更点の説明は、すぐにメインのドキュメントに掲載されました。現在、それらは「カナリア」セクションの下に表示されます。

反応の使用

冒頭で、Next.js は現在 React.js の RC バージョンを使用していると述べました。しかし実際には、これは完全に真実ではない、というよりも完全に真実ではありません。実際、Next.js は現在 2 つの React.js 構成を使用しています。App Router 用の 19 番目の Canary バージョンと 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 devrels の問題のトラブルシューティングを行うときに確実に使用されるでしょう (はい、問題の解決に役立つこともあります)。

Next.js v— Reflecting on Mistakes
[プロジェクトのビルドが遅いことに関するツイート](https://x.com/darshansrc/status/1797339543571755425)に対するNext.jsチームの反応

ビルドプロセスの変更

DX について議論した後は、構築プロセスについても話す価値があります。それに伴い、ターボパックも登場します。

ターボパック

そして、この分野での最大のニュースです。 Turbopack の開発モードが完全に完成しました。 「Turbopack を使用すると、既存のテストの 100% がエラーなしで合格しました」

現在、Turbo チームは製品版の開発に取り組んでおり、徐々にテストを経て改良を加えています (現在約 96% 完了)

Next.js v— Reflecting on Mistakes
next.js の変更ログ セクションの例

Turbopack には新しい機能も追加されています:

  • Turbopack を使用したビルドのメモリ制限を設定する;
  • ツリーシェイキング (未使用コードの削除)。
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
    },
  },
}

もう 1 つの興味深い更新は、静的ページのビルドの再試行です。これは、ページが構築時に失敗した場合 (たとえば、インターネットの問題) に、再度構築が試行されることを意味します。

import type { NextConfig } from 'next';

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

export default nextConfig;

そしてこのセクションの結論として、コミュニティが強く望んでいた機能、つまりビルド用の追加ファイルへのパスを指定する機能です。このオプションを使用すると、たとえば、ファイルがアプリ ディレクトリではなく、modules/main、modules/invoices などのディレクトリに配置されるように指定できます。

ただし、現時点ではチーム内部の目的でのみ追加されています。そしてこのバージョンでは、それは絶対に表示されません。今後は、Vercel のニーズに合わせて使用​​されるか、テストされて次のリリースで提供される予定です。

フレームワーク API の変更点

Next.js の更新で最も面倒な部分は、API の変更です。そしてこのバージョンには、緊急アップデートもあります。

Cookie、ヘッダー、パラメータ、searchParams など、いくつかの内部フレームワーク API が非同期になりました (いわゆるダイナミック API)。

const nextConfig = {
  experimental: {
    staticGenerationRetryCount: 3,
  },
}

これは大きな変更ですが、Next.js チームは、codemod を呼び出すことでこのすべての機能を自動的に更新できることを約束します。

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

もう 1 つの変更ですが、おそらく多くの人には関係ありません。キー 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 のキャッシュ。贈り物か呪い」の記事で主に説明されています。

キャッシュの主な変更点をすべて見てみましょう:

  • 具体的には、フェッチではデフォルトで強制キャッシュではなく 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 は、モジュールを毎回再度ロードするのではなく、モジュールをキャッシュして再利用します。

それは「歴史の誤解」についてです。 Next.js には新しい API も登場します。つまり、いわゆるダイナミック I/O です。まだどこにも書かれていないので、以下は変更点を踏まえた筆者の推測となります。

動的 I/O は、動的構築の高度なモードのようです。 PPR (Partial Prerendering) のようなもの、より正確にはその補完物です。つまり、部分事前レンダリングはページ構築モードであり、ほとんどの要素は構築時に構築されてキャッシュされますが、個々の要素はリクエストごとに構築されます。

つまり、動的 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


部分プリレンダリングの仕組み

この機能自体は、6 か月前に実験 API としてリリース候補に導入されました。この API はこの状態のままであり、おそらくバージョン 16 でのみ安定していると見なされます (主要な機能は 6 か月から 1 年以内に安定に移行することが多いため、これは良いことです)。

変更点について。前述したように、主に動作原則が更新されました。ただし、PPR を使用するという観点から見ると、これはほとんど影響を与えません。同時に、いくつかの改善も加えられました。

以前は、設定にフラグが存在するだけでしたが、PPR を有効にするには、「incremental」を指定する必要があります。これは明らかにロジックをより透過的にするために行われます。開発者はコンテンツを 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',
      },
    ],
  },
}

もう 1 つの変更は、部分フォールバック プリレンダリング (PFP​​R) です。まさにこの改善により、事前に構築された部分が即座にクライアントに送信され、残りの部分は動的にロードされます。この間、動的要素の代わりにコールバック コンポーネントが表示されます。

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>;
  )
}

計装

インストルメンテーションは安定した API としてマークされています。インストルメンテーション ファイルを使用すると、ユーザーは Next.js サーバーのライフサイクルに接続できるようになります。これはアプリケーション全体にわたって機能します (Pages Router と App Router のすべてのセグメント を含む)。

現在、インストルメンテーションは次のフックをサポートしています:

register - Next.js サーバーの初期化時に 1 回呼び出されます。可観測性ライブラリ (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 チームは誤った決定を下し、リリースを急ぎ、コミュニティからのフィードバックにもかかわらず自分たちの意見を守り続けました。問題を認識するまでにほぼ1年かかりました。そして今、ようやく、このフレームワークが再びコミュニティの問題に取り組んでいるという感覚が生まれています。

一方で、他のフレームワークもあります。 1 年前の 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


2024 年 8 月からの ChatGPT の Remix への切り替えに関するツイート

一般に、次の stateofjs と stackoverflow の調査では、大幅な入れ替えが行われる可能性があります。

クレジット

コード例またはその基礎は、next.js ドキュメント、コミット、PR、next.js コアから引用されています。

追記

MD ファイルに基づいてドキュメントを生成するツールが必要な場合は、robindoc.com を参照してください。next.js を使用している場合は、nimpl.tech のソリューションで役立つものが見つかるかもしれません。

以上がNext.js v— 間違いを振り返るの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。