## 本文整理學習 Nextjs 相關的知識與文件<br/>來源來自於網路及自我整理
###### 路由使用 app router 方式
###### 部分內容可能跟 page router 不同
# node js 版本
使用 v20.11.1 最新版本可能造成編譯錯誤
# vs code debug build
launch.json
```json=!
{
// 如需詳細資訊,請瀏覽: https://nextjs.org/docs/pages/building-your-application/configuring/debugging
"version": "0.2.0",
"configurations": [
{
"name": "Next.js: debug server-side",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev"
},
{
"name": "Next.js: debug client-side",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000"
},
{
"name": "Next.js: debug full stack",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev",
"serverReadyAction": {
"pattern": "- Local:.+(https?://.+)",
"uriFormat": "%s",
"action": "debugWithChrome"
}
}
]
}
```
# 編譯腳本
內容寫在 package.json
example:
```json=!
{
"name": "qpp-web-next",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"static_github": "next build && touch ./out/.nojekyll"
},
"dependencies": {
"react": "^18",
"react-dom": "^18",
"next": "14.1.3"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
"postcss": "^8",
"tailwindcss": "^3.3.0",
"eslint": "^8",
"eslint-config-next": "14.1.3"
}
}
```
script 裡面可以寫自己需要的腳本
如 static_github 內容是編譯 github pages 靜態網頁用
除了會跑原本的 build 以外還會額外產出 nojekyll 檔案
讓 github pages 不會略過帶有底線的資料夾
呼叫使用
```shell=!
npm run <command>
```
ex:
```shell=!
npm run build
```
# next.config
next.config.mjs 和 next.config.js 是用於配置 Next.js 應用程式的配置檔案,兩者的主要區別在於檔案格式和支援的特性。
檔案格式:
next.config.mjs 使用 ECMAScript 模組 (ESM) 格式,因此您可以在檔案中使用 import 和 export 語法。
next.config.js 使用 CommonJS 格式,因此您應該使用 require() 和 module.exports 來匯入和匯出模組。
特性支援:
next.config.mjs 支援更先進的 JavaScript 功能,如 ES 模組、動態 import() 等。
next.config.js 在功能上相對保守,不支援一些 ES 模組特性。
> 因此,如果您的專案使用了較新的 JavaScript 特性或者想要使用 import 和 export 語法,建議選擇使用 next.config.mjs。否則,可以繼續使用傳統的 next.config.js。在選擇檔案格式時,您應該根據您的專案需求和團隊技術棧來決定。
[JavaScript 模塊 MDN Web Doc](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules)
# CSR & SSR

我們用上面這張圖來瞭解兩者的差異,如果是 CSR 瀏覽器請求 HTML 後,必須等待請求 JS 檔案,然後再等待 React 把元件 mount 到 DOM上,以及請求 API 還會花費額外的時間。
此外,有些網站很注重搜尋引擎優化 (SEO),搜尋引擎的原理即是爬蟲,而爬蟲通常不包含請求 HTML 後再請求 JS 檔案,所以如果是一般透過前端請求 API 後才載入資料,搜尋引擎便看不到網頁實際上的內容,不利於 SEO。
如果是 SSR,網頁的內容都會在伺服器端處理,爬蟲看到的即是包含完整內容的 HTML,便有利於進行 SEO。同時也有助於減少使用者從請求網頁到看見網頁內容時間,提升使用者體驗 (UX)。

CSR 與 SSR 主要不一樣的點在於多了一個渲染伺服器,渲染伺服器會用於第一次使用者請求 HTML 時,會將內容都事先放到 HTML 中,所以使用者看到的就是一個已經包含完整內容的網頁。
以下包含 React SSR 幾個重點:
擁有一個獨立的伺服器 (後端),提供 API 可以請求資料。
渲染伺服器與瀏覽器端都可以請求 API。
渲染伺服器會在使用者請求 HTML 時,會請求 API 的資料,並將內容都事先放到 HTML 中。
在第一次請求 HTML 後,之後的元件 routing、請求 API 都是在瀏覽器端執行。
> 以上自 [React SSR | 從零開始實作 SSR — 基礎篇](https://medium.com/手寫筆記/server-side-rendering-ssr-in-reactjs-part1-d2a11890abfc) 轉載
# 靜態資源
Next.js 可以在頂層 `public` 目錄 下運行靜態資源,例如圖片。就像 pages 一樣,`public` 目錄中的檔案可以在根目錄下被引用。
`public` 目錄對於 robots.txt、Google Site Verification 或任何靜態資源都很有用。
# apple-touch-icon
用來設定蘋果 (Apple) iOS Safari 將網頁 - 通常是一個 Progressive Web Apps (PWAs) 網頁 - 新增到桌面時的圖示:
```xml=!
<link
rel="apple-touch-icon"
sizes="180x180"
href="/favicon/apple-touch-icon.png"
/>
```
如果沒設定 apple-touch-icon Apple 會自己幫你用 screenshot 建立一個圖示。
常見的 touch icon 尺寸可以是 180x180 pixels 或 192x192 pixels!
# favicon, icon...
```typescript=!
import Footer from "@/app/_components/footer";
import { CMS_NAME, HOME_OG_IMAGE_URL } from "@/lib/constants";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: `Next.js Blog Example with ${CMS_NAME}`,
description: `A statically generated blog example using Next.js and ${CMS_NAME}.`,
openGraph: {
images: [HOME_OG_IMAGE_URL],
},
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<head>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/favicon/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon/favicon-16x16.png"
/>
<link rel="manifest" href="/favicon/site.webmanifest" />
<link
rel="mask-icon"
href="/favicon/safari-pinned-tab.svg"
color="#000000"
/>
<link rel="shortcut icon" href="/favicon/favicon.ico" />
<meta name="msapplication-TileColor" content="#000000" />
<meta
name="msapplication-config"
content="/favicon/browserconfig.xml"
/>
<meta name="theme-color" content="#000" />
<link rel="alternate" type="application/rss+xml" href="/feed.xml" />
</head>
<body className={inter.className}>
<div className="min-h-screen">{children}</div>
<Footer />
</body>
</html>
);
}
```
# css 模組
CSS 模組可以匯入到 `app` 目錄中的任何檔案中:
###### `app/dashboard/layout.tsx`
```ts=!
import styles from './styles.module.css'
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section className={styles.dashboard}>{children}</section>
}
```
CSS 模組是一個可選功能,僅對副檔名為 `.module.css` 的檔案啟用。 仍然支援常規 `<Link>` 樣式表和全域性CSS檔案。
在 production 中,所有 CSS 模組檔案將自動連接成許多縮小和程式拆分的 `.css` 檔案。 這些 `.css` 檔案代表應用程式中的熱執行路徑,確保為應用程式繪製最少的 CSS 載入量。
###### `app/dashboard/styles.module.css`
```css=!
.dashboard {
padding: 24px;
}
```
# 全域性樣式
全域性樣式可以匯入到 `app` 目錄中的任何佈局、頁面或元件中。
例如,創建一個 `app/global.css`
寫入以下內容:
```css=!
body {
padding: 20px 20px 60px;
max-width: 680px;
margin: 0 auto;
}
```
在 root layout 裡(`app/layout.tsx`) 匯入 `globa.css`
此樣式將應用到所有頁面
```ts=!
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
```
外部樣式可以從 `app` 資料夾的任何地方被引入:
```ts=!
import 'bootstrap/dist/css/bootstrap.css'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className="container">{children}</body>
</html>
)
}
```
> 外部樣式必須直接從 npm package 匯入或下載
> 並與您的程式庫一起放置
> 不能使用`<link rel="stylesheet" />`。
# Next.js 元件
## Link
```typescript=!
import Link from "next/link";
```
Link 元件可以允許在同一個 Next.js 應用程式中的兩個頁面之間進行客戶端的頁面跳轉 客戶端導航意味著頁面轉換時使用 JavaScript,這比瀏覽器內建的預設跳轉方法更快。
```xml=!
<Link href="/">Back to home</Link>
```
```xml=!
<Link href="/posts">this page!</Link>
```
Next.js 會自動進行程式碼拆分,所以每個頁面只載入該頁面所需的內容。 這意味著在渲染首頁時,初始化的過程不會載入其他頁面的程式碼。
在 Next.js 的生產版本中,每當 Link 元件出現在瀏覽器的顯示裝置中時,Next.js 都會在後台自動提前載入連結頁面的程式碼。當您單擊連結時,目標頁面的代碼已經在背景執行加載,所以頁面轉換幾乎是即時的!
> Note: 如果您需要鏈接到 Next.js 應用之外的 外部連結 頁面,只需使用不帶 `<Link>` 的 `<a>` 標籤
> 如果您需要添加屬性,例如,`<className>`,請將其添加到 `<a>` 標籤,而非添加到 `<Link>` 標籤。這是一個範例.
## Image
```typescript=!
import Image from "next/image";
```
`next/image` 是為了現代網頁的需求,而在 HTML `<img>` 基礎之上建立的擴展元件。
在預設情況下 Next.js 支援圖片優化。包括了支援現代 web 格式,且進行大小調整、優化和運行圖片 (就像 WebP 一樣),這避免了在較小的可見區域加載大型圖片。同時,Next.js 還可以自動適應未來的圖片格式,並將其提供給支援這些格式的瀏覽器。
自動圖片優化可與任何圖片一起使用。即使圖片由外部數據源(例如 CMS)托管,它仍然可以進行優化。
Next.js 在使用者發出請求時,會動態優化圖片,而非在建置時進行優化。這與靜態網站產生器以及僅支援靜態內容的解決方案不同,不論是上傳 10 張還是 1 千萬張圖片,都不會增加建置時間。
圖片默認採用「懶加載」方式,這意味著圖片不在可見區域時不會影響頁面速度。當圖片被滾動到可見區域時才會加載。
圖片總是以避免累積版面位移的方式呈現,這是 Google 會在搜尋排名中使用的核心網頁指標。
```typescript=!
<Image
src="/vercel.svg"
alt="Vercel Logo"
className="dark:invert"
width={100}
height={24}
priority
/>
```
## Head
```typescript=!
import Head from "next/head";
```
可以設置 詮釋資料(Metadata)
```xml=!
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
```
> 若想了解更多有關 Head 元件的資訊,請參閱 `next/head` 的 API 參考。
>
> 若想自訂 `<html>` 標籤,像是加入 `lang` 屬性,你可以透過建立 `pages/_document.js` 檔案來達成,詳細資訊請參閱 [自訂 Document 文件](https://nextjs.tw/docs/advanced-features/custom-document)。
> ps.目前版本需再確認
## Script
```typescript=!
import Script from "next/script";
```
`next/script` 是基於 HTML`<script>` 元素的擴充功能,可優化提取和執行其他腳本的時機。
```xml=!
<>
<Head>
<title>First Post</title>
</Head>
<script src="https://connect.facebook.net/en_US/sdk.js" defer />
<h1 className="title">
Read <Link href="/posts/first-post">this page!</Link>
</h1>
</>
```
在 Next.js 中,`<script>` 標籤有一個屬性叫做 `async`,這個屬性告訴瀏覽器在加載該腳本時不需要等待,可以同時加載其他資源。
使用 `async` 屬性的 `<script>` 標籤會異步加載腳本,在腳本下載完成後立即執行。這意味著該腳本的執行可能在頁面的其他資源加載完成之前開始。
這個屬性對於需要立即執行但對頁面內容不是必需的腳本非常有用,例如分析程式碼、社交分享按鈕等。
需要注意的是,使用 `async` 屬性的腳本不保證按照它們在頁面上出現的順序執行。如果您需要確保腳本按照指定順序執行,可以考慮使用 `defer` 屬性代替 `async` 屬性。
# TypeScript 參考
* [[掘竅] 了解這些,更快掌握 TypeScript 在 React 中的使用(Using TypeScript in React)](https://pjchender.blogspot.com/2020/07/typescript-react-using-typescript-in.html)
* [讓 TypeScript 成為你全端開發的 ACE!](https://ithelp.ithome.com.tw/users/20120614/ironman/2685)
* [ 學了 React 後的下一步?準備好兩把刷子!](https://pjchender.dev/ironman-2021/ironman-2021-day01/)
* [TypeScript Omit 的用法](https://blog.marsen.me/2022/09/12/2022/TypeScript_Omit/)
* [TypeScript 新手指南](https://willh.gitbook.io/typescript-tutorial/basics/declaration-files)
# 相關網站
* [前端框架簡介](https://developer.mozilla.org/zh-TW/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction)
* [為什麼你需要 Next.js](https://ithelp.ithome.com.tw/articles/10265138)
* [快速上手 NextJS v13 - 基礎觀念 AppRouter 篇](https://johnnywang1994.github.io/book/articles/js/next13-intro-approuter.html)
* [來做 Facebook 貼文串的前端吧!中(設計參考)](https://medium.com/@qaz7821819/五分鐘學前端系統設計面試-五-來做-facebook-貼文串的前端吧-中-fd2fb34bde19)
* [Next.js 官方文件](https://nextjs.org/docs)
* [Next.js 中文官方文件(已無更新)](https://nextjs.tw/docs/getting-started)
* [Next.js sample on github](https://github.com/vercel/next.js/tree/canary/examples)
* [該怎麼知道網站是 CSR 還是 Pre-Rendering](https://ithelp.ithome.com.tw/articles/10314924)
* [SSR 與 CSR 深度解析:從渲染方式到效能優化](https://www.shubo.io/rendering-patterns/)
* [不用寫程式也能產生 API — strapi](https://medium.com/黑洞創造-blackhole-creative/不用寫程式就能產生-api-strapi-工具介紹-f40d01570322)
* [tailwind css](https://tailwindcss.com/docs/min-height)
* [tailwindcss - 從零開始學](https://ithelp.ithome.com.tw/users/20162607/ironman/6658)
# Trouble
[Next.js not fully functional on Safari for iOS 12 #48627](https://github.com/vercel/next.js/issues/48627)