➜ Old React website
Chung Cheuk Hang MichaelJava Web Developer
Spring 項目中訂閱 KafkaJasperReports

用 Next.js 建立 React 網站

Continued from previous post:
React JS 網頁開發筆記(一)

Table of contents

1 Next.js 簡介

React 係一個畀 web developers 好大自由度既 front-end development library。
  • 我地可以選擇唔同既 build tools、project structures 去建立 React 項目。不過,咁就會搞到每個 React 項目都可以有佢自己既一套做法,而缺乏一個統一既標準。
  • 除此之外,純 React 網站因為唔係 static HTML,所有網頁內容都要靠 JavaScript,所以係做唔到 search engine optimization(SEO)。
Next.js 係一個 React 既 framework,佢唔單止可以解決呢啲問題,仲有一啲有用既附加功能。
  • Next.js 有自己既一套 project structure 標準(根據目錄、檔案)做 page routing。
  • Next.js 最重要既功能係 static site generation(SSG)以及 server-side rendering(SSR),冇左就做唔到 search engine optimization(SEO)。
  • 可以實現 front-end + back-end monolith,可以 build 成一個基於 NodeJS runtime 既網站。
  • 為左提升 static HTML 網頁 navigation 既 performance,Next.js 既 Link 帶有 prefetch 功能,喺背後 fetch 網站使用者有機會會瀏覽既下一個網頁。
  • 自帶 modular CSS 功能,我地可以寫 xxx.module.css 檔案,Next.js 會自動用上隨機既 class names,做到 React components 各自有唔同既 CSS。
  • 原生支援 render MDX 既 Markdown,令到寫 static blog 好方便。
方面組件
Build toolNext.js bundle 左既 Turbopack 或者 Webpack
Build scriptsNext.js
JavaScript、TypeScript compilerNext.js bundle 左既 SWC
Page routingNext.js(file-based page routing)

1.1 比較 Vite

Vite 只係一個 build tool,所以所有 build tool 以外 Next.js 既功能 Vite 都係冇既。
而用左 Next.js 之後,就唔可以用 Vite 黎 build 個項目。
而對比起 Vite,Next.js 生成出黎既項目既 node_modules 裡面既檔案、目錄數量都係比較多。

1.2 App Router vs Page Router

Next.js 一直都只有「Page Router」去做 page routing,而自從 Next.js 13 就多左個「App Router」功能。
App Router 支援 React Server Components(RSC),而 Page Router 就唔支援。
Before Next.js 13, the Pages Router was the main way to create routes in Next.js. It used an intuitive file-system router to map each file to a route. The Pages Router is still supported in newer versions of Next.js, but we recommend migrating to the new App Router to leverage React's latest features.
簡單黎講,用新既 App Router 會比較好。
Next.js 既官方文檔有分清楚 router、版本號碼,我地睇文檔既時候記得揀岩就得。

2 動手做

我地會部署一個 Next.js static site generation(SSG) 既網站上 GitHub Pages。

2.1 安裝 Create-Next-App

npm i -g create-next-app

2.2 生成 ReactJS 項目

創建一個新 folder,然後喺裡面執行:
npx create-next-app
我地既項目名係 my-react-app-nextjs
之後需要揀一啲選項:
  1. TypeScript:No
  2. ESLint:No
  3. Tailwind CSS:No
  4. src/ directory:Yes
  5. App Router:Yes
  6. Turbopack:No
  7. Customize import alias:No

2.3 執行 ReactJS 項目

喺生成出黎既 ReactJS 項目既 project root folder 度執行:
npm i
等佢下載所有 npm modules,之後就可以執行:
npm run dev
然後喺本地瀏覽器打開 http://localhost:3000
OS 既防火牆 allow 左 node.exe 之後,可以喺 LAN 既其他裝置打開 http://192.168.1.X:3000

2.4 部署到 GitHub Pages

2.4.1 創建 GitHub repository

  1. 登入 GitHub,然後新增一個 public repository。
  2. 喺本地 git clone 呢個新既 Git repo。
  3. .git 檔案搬到我地用 Create-Next-App 建立既項目既 project root folder 裡面。

2.4.2 喺 ReactJS 項目加入 gh-pages

喺 ReactJS 項目既 project root folder 執行:
npm i gh-pages
之後喺 package.jsonscripts field 裡面加入 predeploy 以及 deploy
1{ 2 "scripts": { 3 "dev": "next dev", 4 "build": "next build", 5 "start": "next start", 6 "lint": "next lint", 7 8 "predeploy": "npm run build", 9 "deploy": "gh-pages --nojekyll -d out" 10 } 11}
註:
  • predeploy 呢個 script 名係 deploy 既 pre script,而 pre script 係 npm 提供既功能。
    • Pre script 會喺佢「pre」既對象既 script 執行之前執行。
    • predeploy 會喺 deploy 執行之前執行。
  • 部署流程:
    1. predeploy script 會幫我地執行 npm run build,而 npm run build 對應 build script,會執行 next build,生成 out folder。
    2. deploy script 會執行 gh-pages 既邏輯,將 -dout folder 部署上我地 Git repo 作為 GitHub Pages。

2.4.3 修改 Next.js 配置

我地要將 base path 寫落 next.config.mjs,並且加上 output option:
1/** @type {import('next').NextConfig} */ 2const nextConfig = { 3 basePath: "/my-react-app-nextjs", 4 output: "export", 5}; 6 7export default nextConfig;

2.4.4 修改 image base path

雖然我地喺 Next.js 配置度加左 base path,但 Next.js 唔會好似 Vite 咁自動幫我地改 <img> 或者 next/imageImage 既 base path,不過我地可以用 process.env.__NEXT_ROUTER_BASEPATH 呢個 environment variable。
src/app/page.js 裡面全部既:
<Image src="/xxx.yyy" />
都要改成:
<Image src={`${process.env.__NEXT_ROUTER_BASEPATH}/xxx.yyy`} />

2.4.5 部署 ReactJS 項目到 GitHub Pages

喺 ReactJS 項目既 project root folder 執行:
npm run deploy

3 檢視結果

3.1 Source map

Production build 唔應該有 source map,我地可以睇下 out folder 裡面有冇 source map。
答案係冇既,因為 Next.js 默認既 productionBrowserSourceMaps 配置係 false,所以 Next.js 打包 out folder 既時候默認係唔會生成 source map。

3.2 GitHub Pages 網站

等一陣,GitHub Pages 會 host 我地既網站:

3.3 Static HTML

我地可以用 cURL 下載我地 React 網站既某個網頁,睇下下載落黎既 HTML 檔案係咪已經包含果頁既內容。
如果唔用 Next.js 做 static site generation(SSG)或者 server-side rendering(SSR)既話,純 React 既網站係 dynamic HTML,即係要行左 client-side JavaScript 之後先至可以顯示到頁面內容。
curl https://blackr1234.github.io/my-react-app-nextjs/
我地會見到(以下用左 XML formatter):
1<body class="__variable_9011bf __variable_8dcd95"> 2 <div class="page_page__ZU32B"> 3 <main class="page_main__GlU4n"> 4 <img alt="Next.js logo" width="180" height="38" decoding="async" data-nimg="1" class="page_logo__7fc9l" style="color:transparent" src="/my-react-app-nextjs/next.svg"/> 5 <ol> 6 <li>Get started by editing <code>src/app/page.js</code>.</li>
即係話我地既網站係 static HTML 而唔需要靠執行 JavaScript。
如果我地喺網頁瀏覽器度 disable 左 JavaScript,我地會發現,純 React 寫既網站係會顯示空白頁面,但我地呢個 Next.js 既網站仲可以正常運行。

4 參考資料