Closed32

Learn Next.js App Router Course を雑にまとめる

りょたりょた

テイルウィンドで遊ぼう!以下のコードをコピーし、次の<p>要素の上に貼り付けます

<div
  className="h-0 w-0 border-b-[30px] border-l-[20px] border-r-[20px] border-b-black border-l-transparent border-r-transparent"
/>

https://nextjs.org/learn/dashboard-app/css-styling

vercelの三角形のロゴが表示される。

りょたりょた

Provide a way to make CSS classes locally scoped to components by default, enabling better modularity and reducing the risk of styling conflicts.
CSS クラスをデフォルトでコンポーネントにローカルにスコープする方法を提供し、モジュール性を向上させ、スタイルの競合のリスクを軽減します。
https://nextjs.org/learn/dashboard-app/css-styling

この言語化も良きですね。

りょたりょた
className={clsx(
        'inline-flex items-center rounded-full px-2 py-1 text-xs',
        {
          'bg-gray-100 text-gray-500': status === 'pending',
          'bg-green-500 text-white': status === 'paid',
        },
      )}

オブジェクトのtrueのキーが文字列として出力される。
あんまりこの書き方をしてこなかった。

clsxは今まで下記の書き方でした。

className={clsx(
        'inline-flex items-center rounded-full px-2 py-1 text-xs',
          status === 'pending' && 'bg-gray-100 text-gray-500',
        status === 'paid' &&    'bg-green-500 text-white'
      )}

参考
https://github.com/lukeed/clsx

りょたりょた

Furthermore, in a production, whenever <Link> components appear in the browser's viewport, Next.js automatically prefetches the code for the linked route in the background
Next.js がリンクされたルートのコードをバックグラウンドで自動的にプリフェッチします。
https://nextjs.org/learn/dashboard-app/navigating-between-pages

以前からこの挙動でしたっけ?
ホバー時にプリフェッチする挙動からビューポートに入った時にプリフェッチする挙動にいつから変わったのか🤔

りょたりょた

However… there is one disadvantage of using this JavaScript pattern: what happens if one data request is slower than all the others?
https://nextjs.org/learn/dashboard-app/fetching-data

Promise.all でいずれかのAPIのレスポンスが極端に遅い場合、それを待つ必要がある。

With dynamic rendering, your application is only as fast as your slowest data fetch.
https://nextjs.org/learn/dashboard-app/static-and-dynamic-rendering

データフェッチのタイミングは並行していても、レンダリングは最も遅いAPIレスポンスに引っ張られることが課題。

りょたりょた

URL パスに影響を与えずにルートを整理する
URL に影響を与えずにルートを整理するには、グループを作成して関連するルートをまとめます。括弧内のフォルダーは URL から省略されます (例(marketing): または(shop))。
https://nextjs.org/docs/app/building-your-application/routing/route-groups

Fixing the loading skeleton bug with route groups
Right now, your loading skeleton will apply to the invoices and customers pages too. This is because in Next.js, files nest inside each other. Since loading.tsx is a level higher than /invoices/page.tsx and /customers/page.tsx, it's also applied to those pages.
https://nextjs.org/learn/dashboard-app/streaming

ほかのセグメントでも必要なLayout.tsxだけ外に出しておける。

りょたりょた

個々のカードのデータをフェッチすることはできますが、カードが読み込まれるときにポップ効果が発生する可能性があり、ユーザーにとって視覚的に不快になる可能性があります。
https://nextjs.org/learn/dashboard-app/streaming

視覚的に不快にならない程度のエリアでsuspenseを利用する。

りょたりょた

Where you place your Suspense boundaries will depend on a few things:
How you want the user to experience the page as it streams.
What content you want to prioritize.
If the components rely on data fetching.
ストリーミング中にユーザーにページをどのように体験してもらいたいか。
どのコンテンツを優先したいか。
コンポーネントがデータの取得に依存している場合。
https://nextjs.org/learn/dashboard-app/streaming

りょたりょた

現時点では、ルート内で動的関数noStore()(たとえば、cookies()、など) を呼び出すと、ルート全体が動的になります。
実際には、ほとんどのルートは完全に静的または動的ではありません。静的コンテンツと動的コンテンツの両方を含むルートがある場合があります。たとえば、ソーシャル メディア フィードがあるとします。投稿は静的ですが、投稿に対する「いいね!」は動的になります。または、商品の詳細は静的ですが、ユーザーのカートは動的である e コマース サイト。

PPR はどのように機能しますか?
PPR は React の同時 API を活用します、サスペンスを使用します。何らかの条件が満たされるまで (データがロードされるなど)、アプリケーションのレンダリング部分を延期します。
フォールバックは、他の静的コンテンツとともに初期静的ファイルに埋め込まれます。ビルド時 (または再検証中) に、ルートの静的な部分が事前にレンダリングされ、残りの部分はユーザーがルートを要求するまで延期されます。
コンポーネントを Suspense でラップしても、コンポーネント自体が動的になるのではなく (以前にunstable_noStoreこの動作を実現していたことを思い出してください)、Suspense はルートの静的部分と動的部分の間の境界として使用されることに注意してください。
PPR の優れた点は、それを使用するためにコードを変更する必要がないことです。Suspense を使用してルートの動的部分をラップしている限り、Next.js はルートのどの部分が静的でどの部分が動的であるかを認識します。

ここがしっくりきていない。

りょたりょた
import { deleteInvoice } from '@/app/lib/actions';
 
// ...
 
export function DeleteInvoice({ id }: { id: string }) {
  return (
    <form action={deleteInvoice}>
      <input type="hidden" name="id" value={id} />
      <button className="rounded-md border p-1">
        <TrashIcon className="w-4" />
      </button>
    </form>
  );
}

deleteボタンの書き方が以前とはまるで異なる。
onClickイベントだとclient component になるからか。
https://nextjs.org/learn/dashboard-app/mutating-data#deleting-an-invoice

りょたりょた

For example, this plugin warns if you have images without alt text, use the aria-* and role attributes incorrectly, and more.
altテキストのない画像がある場合、 aria-* と role 属性が間違って使用されている場合などに警告します。
https://nextjs.org/learn/dashboard-app/improving-accessibility

まじでアクセシビリティは何もわかっていません。。
そうなんだーという感じ。

りょたりょた

We will be using NextAuth.js to add authentication to your application. NextAuth.js abstracts away much of the complexity involved in managing sessions, sign-in and sign out, and other aspects of authentication. While you can manually implement these features, the process can be time-consuming and error-prone. NextAuth.js simplifies the process, providing a unified solution for auth in Next.js applications.
https://nextjs.org/learn/dashboard-app/adding-authentication

NextAuth使うのかー。auth系のライブラリーだとApp Routerの標準になるのかな。

りょたりょた
import type { NextAuthConfig } from 'next-auth';
 
export const authConfig = {
  providers: [],
  pages: {
    signIn: '/login',
  },
  callbacks: {
    authorized({ auth, request: { nextUrl } }) {
      const isLoggedIn = !!auth?.user;
      const isOnDashboard = nextUrl.pathname.startsWith('/dashboard');
      if (isOnDashboard) {
        if (isLoggedIn) return true;
        return false; // Redirect unauthenticated users to login page
      } else if (isLoggedIn) {
        return Response.redirect(new URL('/dashboard', nextUrl));
      }
      return true;
    },
  },
} satisfies NextAuthConfig;

satisfies 使ってる!感動!こんなん感じで使うんや。

りょたりょた

But what if you want to add a custom title for a specific page? You can do this by adding a metadata object to the page itself. Metadata in nested pages will override the metadata in the parent.
しかし、特定のページにカスタム タイトルを追加したい場合はどうすればよいでしょうか? metadataこれを行うには、ページ自体にオブジェクトを追加します。ネストされたページのメタデータは、親のメタデータをオーバーライドします。
https://nextjs.org/learn/dashboard-app/adding-metadata

overrideされるんや。けっこう使いやすそうなインターフェース。

りょたりょた

The %s in the template will be replaced with the specific page title.
テンプレート内のは、%s特定のページ タイトルに置き換えられます。
https://nextjs.org/learn/dashboard-app/adding-metadata

%sと書くとtitleを差し替えてくれるのか!便利。

export const metadata: Metadata = {
  title: {
    template: '%s | Acme Dashboard',
    default: 'Acme Dashboard',
  },
  description: 'The official Next.js Learn Dashboard built with App Router.',
  metadataBase: new URL('https://next-learn-dashboard.vercel.sh'),
};

export const metadata: Metadata = {
  title: 'Invoices',
};
The document title.

@example

"My Blog"
<title>My Blog</title>

{ default: "Dashboard", template: "%s | My Website" }
<title>Dashboard | My Website</title>

{ absolute: "My Blog", template: "%s | My Website" }
<title>My Blog</title>
このスクラップは2023/10/29にクローズされました