Laurence R.
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Next.js 概述 <center><img src="https://images.prismic.io/techloset/Z1_3cpbqstJ98iN__a-complete-guide-to-next-js-a-react-js-framework.webp?auto=format%2Ccompress&fit=max&w=3840" /></center> 前言 --- 「React 是一個非常出色的 **前端框架 (JavaScript Framework)**,它讓我們能用『元件 (Components)』來打造互動式的『客戶端 (Client-Side)』介面。 但是,當我們用 React 打造一個完整的『應用程式 (Application)』時,尤其是在生產環境 (Production),我們會遇到幾個核心挑戰: - **SEO (搜尋引擎優化) 問題:** 傳統 React (CSR) 交付給瀏覽器的是一個幾乎空白的 HTML 和一包 JavaScript。搜尋引擎爬蟲可能只看到空白頁面,不利於網站排名。我們後續會講解 CSR 以及 **SSR (Next.js 的精隨)** 是甚麼。 - **首屏載入效能 (Initial Load Performance):** 使用者需要先下載完 JavaScript 檔案,然後在瀏覽器上執行 React,才能看到畫面。在網路較慢或設備效能較差時,使用者會面對一段時間的白畫面。 - **架構的功能缺乏性:** 因為 React 這個框架本身只管 UI,所以我們需要自己決定如何處理:**路由 (Routing)**、**資料請求 (Data Fetching)**、**程式碼分片 (Code Splitting)**、**圖片優化**...等等。 **而 Next.js 就是為了解決這些問題而生的。** 但是這個框架它不是來取代 React 的,而是 React 的 **『生產環境框架 (Framework)』**。它在 React 之上,提供了一套完整、高效能的架構和『預設的最佳實踐 (Defaults and Conventions)』,讓我們能專注在業務邏輯,同時免費獲得 SSR、SSG 等強大功能。」 核心概念 (一) - 渲染模式 (Rendering Strategies) - 解決 SEO 與效能 --- ### 四大渲染模式 - **CSR (Client-Side Rendering):** 傳統 React 渲染模式。Next.js 依然支援。 - **客戶端渲染的比喻:** - IKEA 倉庫(伺服器)寄給你一個「包裹」。 - 這個包裹就是**空白的 HTML** 和**一大包 JavaScript(零件和說明書)**。 - 包裹本身不是椅子。你(客戶端瀏覽器)必須在你的客廳裡,自己打開包裹,看著說明書(執行 JS),花時間把椅子「組裝」起來(渲染出畫面)。 - **簡單總結:** 「先拿到一堆零件,然後自己忙半天才能用。」 - **SSR (Server-Side Rendering):** **每次請求 (Request) 都在伺服器上** 產生 HTML。 - **優點:** 對 SEO 友好、使用者能更快看到畫面、適合資料頻繁變動的頁面(例如:會員中心)。 - **伺服端渲染的比喻:** - 你打電話給木工師傅(伺服器),說:「我現在要一張椅子。」 - 師傅 **「立刻」** 在他的工作室(伺服器)裡,為你量身打造這張椅子。 - 完成後,他直接把一張 **「組裝好的完整椅子」**(HTML)運到你家。你一拿到就能立刻使用。 - **簡單總結:** 「向師傅下訂單 **(向伺服器請求)**,然後拿到客製化的成品 **(HTML)**。」每次下單,師傅都會重做一次。 - **SSG (Static Site Generation):** **在建構 (Build Time) 時就** 產生所有 HTML 頁面。 - **優點:** 速度最快(可被 CDN 緩存)、最安全、對 SEO 最好。適合內容不常變動的頁面(例如:部落格文章、行銷頁面)。 - **ISR (Incremental Static Regeneration):** SSG 的進化版。在背景「增量」重新產生靜態頁面,讓靜態網站也能擁有動態更新的資料。 ### CSR (for React) v.s SSR (for Next.js) - Diagram <center><img src="https://hackmd.io/_uploads/Hk4l_AlJWg.png" /></center> 核心概念 (二) - 路由系統 (Routing System) - 解決架構 --- 在過去,頁面的路由上,無論是 Pages Router 還是 React Router,我們的思考都是『一個**檔案**對應一個**頁面**』。 > **Pages Router 範例:** > > - `pages/about.js` → 變成 `/about` 路由 > > - `pages/dashboard.js` → 變成 `/dashboard` 路由 但在 App Router 中,這個思想改變了。 **核心轉變:『一個資料夾代表一個路由 (Route Segment),裡面的 `page.js` 才是該路由的 UI。』** > **App Router 範例:** > > - `app/about/page.js` → 變成 `/about` 路由 > > - `app/dashboard/page.js` → 變成 `/dashboard` 路由 為什麼要這麼麻煩,多一層資料夾?因為這帶來了 App Router 最強大的功能... **巢狀佈局 (Nested Layout)** ### 巢狀佈局 (Nested Layout) <center><img src="https://upload.wikimedia.org/wikipedia/commons/4/4a/%D0%9C%D0%B0%D1%82%D1%80%D1%91%D1%88%D0%BA%D0%B0-Russian_leaders_%E3%83%9E%E3%83%88%E3%83%AA%E3%83%A7%E3%83%BC%E3%82%B7%E3%82%AB_Shimada22.jpg" /></center> 巢狀佈局就好像是「俄羅斯娃娃」一樣,讓網頁變成一層一層嵌套的形式。 **請記住兩個最重要的特殊檔案:** 1. **`layout.js`:** 這就是 **『娃娃的殼』**。它是一個共享的 UI,負責包裹住在它內部的所有東西。 2. **`page.js`:** 這就是 **『娃娃的臉』** 。它是這個路由實際要顯示的、獨一無二的內容。 ``` app/ ├── layout.js # 娃娃 1 (最大隻的娃娃) 的殼 │ # (裡面放 <html>, <body>, Navbar, Footer) │ ├── page.js # 娃娃 1 的臉 (首頁 /) │ └── dashboard/ │ ├── layout.js # 娃娃 2 (中間的娃娃) 的殼 │ # (裡面放 Sidebar) │ ├── page.js # 娃娃 2 的臉 (儀表板首頁 /dashboard) │ └── settings/ │ ├── layout.js # 娃娃 3 (最小的娃娃) 的殼 │ └── page.js # 娃娃 3 的臉 (設定頁 /dashboard/settings) ``` 現在,我們來看當使用者瀏覽不同頁面時,Next.js 是怎麼『組裝』這些娃娃的: * **當使用者去看首頁 (`/`):** * Next.js 會拿 `app/page.js` (首頁的臉) * ...然後把它放進 `app/layout.js` (最大的殼) 裡。 * **結果:** `[Navbar + [首頁內容] + Footer]` * **當使用者去看儀表板首頁 (`/dashboard`):** * Next.js 會拿 `app/dashboard/page.js` (儀表板的臉) * ...把它放進 `app/dashboard/layout.js` (帶有 Sidebar 的殼) 裡。 * ...然後再把**整組**放進 `app/layout.js` (最大的殼) 裡。 * **結果:** `[Navbar + [Sidebar + [儀表板內容]] + Footer]` * **當使用者去看儀表板中的設定頁 (`/dashboard/settings`):** * Next.js 會拿 `app/dashboard/settings/page.js` (設定頁的臉) * ...把它放進 `app/dashboard/layout.js` (Sidebar 的殼) 裡。**(注意:這裡沒有 `settings/layout.js`,所以它會自動找上一層的 `layout` 來用!)** * ...最後再把**整組**放進 `app/layout.js` (最大的殼)。 * **結果:** `[Navbar + [Sidebar + [設定頁內容]] + Footer]`」 ### 示意圖 <center><img src="https://hackmd.io/_uploads/HkVnDGc1Zl.png" /></center> 核心概念 (三) - API 路由 - 整合後端接口 --- Next.js 允許你直接在專案中建立後端 API。 * **如何運作:** 放在 `pages/api/` 或 `app/api/` 資料夾下的檔案,會成為一個 API 端點 (Endpoint)。 * **優點:** 不需要額外架設一個 Node.js 伺服器。非常適合處理簡單的後端邏輯,例如:表單提交、連接資料庫、驗證...等。這就是所謂的 **BFF (Backend for Frontend)**。 <center><img src="https://hackmd.io/_uploads/BJlrDL7JWx.png" /></center> 核心概念 (四) - React Server Components (RSC) --- * **Server Components (伺服器元件):** 預設在 **伺服器端** 執行的元件。它們**不會**被下載到客戶端,JavaScript 體積 (Bundle Size) 為 0。 * **Client Components (客戶端元件):** 傳統的 React 元件。需要互動 (如 `useState`, `onClick`) 的元件,必須加上 `"use client";` 標記。 光看以上對於這兩種 Component 的介紹可能不太懂。沒關係我們講得更清楚一些。 * **Server Components (伺服器元件):** 就像是部落格的文章。當我們進入到部落格的文章頁面時,文章、作者、留言都會被加載,這些東西跟動作都是會透過 Server 去進行資料抓取,**使用者並不需要進行動作**,並且合成一個 HTML 檔案之後丟給客戶端,這些只需要靠 Server 就可以完成的物件,我們稱為 RSC。 * **Client Components (客戶端元件):** 就像是部落格的留言區。你可以點讚、留言,這些動作不可能是由伺服器去幫你執行的,**而這些需要互動屬性的物件**,我們稱為 RCC 。 核心概念 (五) - 內建優化 (Built-in Optimizations) --- Next.js 幫我們處理了很多麻煩的效能優化。 * **`<Image>` 元件:** 自動處理圖片優化(壓縮、轉檔 WebP)、響應式圖片、延遲載入 (Lazy Loading)。 * **`<Link>` 元件:** 簡化前端路由,並自動在背景預先載入 (Prefetch) 連結頁面的資源,讓換頁體感極快。 * **字體優化 (`next/font`):** 自動處理 Google Fonts 或本地字體,避免「字體閃爍 (FOUT)」和「版面位移 (Layout Shift)」。 --- 文件參考:https://nextjs.org/docs

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully