跳到主要內容

FE Day 39 效能實戰

FE Day 39 效能實戰

執行需求:CPU 可跑。今天是「前端開發實戰:React 與 Next.js 全套」系列的第三十九天,貫穿專案「預約管理系統前端」正式進入收尾階段。今天只做一件事:把從 Day 1 到 Day 38 累積的所有畫面、表單、API、登入流程,做一次完整的效能體檢,並把可改進的空間落到具體的程式碼。我們會用 Next.js 15 內建的 @next/bundle-analyzer、React 19 的 <Profiler> 元件、Lighthouse 桌面版、以及 Day 30 提到的 lib/monitor.ts 抽象層,在本機端做完整量測。今天所有資料都是虛構示範,跟 Web 系列 Day 35–44 的 FastAPI 後端契約完全對齊,無後端在跑時用內建 mock 模式(標示清楚)。

引言

效能調校是前端最容易被低估的工作之一。看起來「先讓畫面能跑就好」,但實際上線後會發現:第一個畫面 LCP 8 秒、按鈕按下去 INP 600 毫秒、滑動時 CLS 跳 0.3,這些數字直接影響跳出率與轉換率。貫穿專案預約管理系統的目標使用者是「想預約的客戶」與「服務提供者」,他們通常用手機、3G 或家裡 Wi-Fi,耐心非常有限。今天把 Day 25 的 Core Web Vitals 基礎、Day 26 的圖片與字型最佳化、Day 30 的監控層,全部整合到「預約系統前端」這套具體的程式碼上,並把能改的、能跑的、能驗證的都做完。

貫穿專案「預約管理系統」是個小型服務業線上預約平台(情境涵蓋攝影棚、健身教練、諮詢工作室,所有資料都是虛構示範)。前 38 天已經把這套系統的路由、頁面、表單、登入、後台、錯誤處理做完。今天要做的效能實戰分成四個層次:衡量(怎麼量、量什麼)、拆解(bundle 怎麼分、route 怎麼切)、最佳化(圖片、字型、cache、preload)、守護(設定效能預算、未來回歸怎麼抓)。這四層缺一不可:沒有衡量就不知道瓶頸、沒有拆解就無法平行最佳化、沒有最佳化就不會進步、沒有守護就會在下次改版時把今天做的一切抹掉。

今天的內容分四段:第一段把 Day 31–38 的共用設定再次統一;第二段講效能衡量(Core Web Vitals、Profiler、Bundle Analyzer);第三段講實戰最佳化(dynamic import、next/image、route segment caching、cache headers);第四段設定效能預算與 CI 守護。讀完之後你會拿到一份能在自己機器上跑的量測腳本、一份可貼上的最佳化清單、以及一份能在 CI 跑的回歸檢查。

貫穿專案共用設定(Day 31–44 沿用)

今天所有量測與最佳化都建立在 Day 31–38 已經定好的 stack 上:

  • 框架:Next.js 15(App Router、Server Components 預設、Turbopack 穩定版)、React 19.x、TypeScript 5.9
  • 樣式:Tailwind CSS 4.x、CSS variables 主題、Heroicons
  • 後端:FastAPI 預約管理系統(Web 系列 Day 35–44 定義的 REST API)
  • 認證:JWT access token(12 小時,存記憶體)、refresh token(14 天,httpOnly cookie);沿用 Day 38 的 AuthProvider
  • 角色:admin(管理者)、customer(客戶)
  • 狀態管理:TanStack Query 5.x(伺服器狀態)、React 19 useState/useReducer(UI 狀態)、Context(使用者狀態)
  • 監控:Day 30 的 lib/monitor.ts(Sentry 雲端 + 本地 Noop 雙軌)
  • Mock 模式:NEXT_PUBLIC_API_MODE=mock 時走 lib/mock/*.ts fixture,不打真實 API;正式模式 live

這份設定從 Day 31 到 Day 44 不變。效能調校是在這份設定上「加東西」而不是「改東西」:我們加量測、加快取、加分塊,但不會改路由結構或 API 契約。理解這點才能看懂今天為什麼每個改動都盡量小範圍、為什麼要設定效能預算當 CI 守護。

原理解念:Core Web Vitals 與 RAIL 模型

Core Web Vitals 是 Google 在 2024 年正式定為搜尋排名依據的三個指標,2026 年 3 月仍是主流衡量基準。第一個是 LCP(Largest Contentful Paint,最大內容繪製),衡量「主要內容」繪製完成的時間,目標 2.5 秒以內。第二個是 INP(Interaction to Next Paint,互動到下次繪製),衡量使用者點選按鈕到畫面真的更新回應的時間,目標 200 毫秒以內。第三個是 CLS(Cumulative Layout Shift,累計版面位移),衡量頁面載入過程中元素意外位移的程度,目標 0.1 以下。這三個指標分別對應「載入慢」、「互動卡」、「畫面跳」三種最常見的抱怨。

RAIL 模型(Response、Animation、Idle、Load)則給出更細的時間預算:使用者點選的回應要在 100 毫秒內開始、動畫要在 16 毫秒(60fps)內完成一幀、idle 時要把大工作切小、load 要在 1 秒內完成主要內容。Core Web Vitals 其實就是 RAIL 模型的具體化:LCP 對應 Load、INP 對應 Response 與 Animation、CLS 對應 Idle 階段的版面穩定。我們今天的所有量測都會回頭對到這三個指標,並把每個指標的具體成因列出來。

React 19 提供了 <Profiler> 元件可以量「元件渲染時間」:每個元件掛載或更新花多少毫秒、commit 階段多久、互動處理到畫面更新多久。Profiler 會把資料送到 onRender callback,我們可以選擇送到 console、Sentry、甚至自製的時序資料庫。Profiler 的取樣成本極低(在 production 也可以開),但要記得把資料送到外部時做隱私過濾(沿用 Day 30 的 beforeSend 機制)。

bundle 體積是另一個常被忽略的指標。Next.js 預設會把每個 route 的 JS 切成獨立的 chunk,使用者進入首頁時只下載首頁需要的程式,但實際 chunk 怎麼切、取捨策略是誰決定的,都是配置層的選擇。@next/bundle-analyzer 把每個 chunk 內含哪些模組、每個模組多大視覺化成可互動的 treemap,讓你一眼看出「為什麼這個頁面下載了 300KB」。這個工具是 Day 16 專案結構討論的延伸:我們刻意把元件按功能分類(components/ui/、components/booking/、components/admin/),現在 bundle analyzer 會驗證這個分類是否真的讓首頁不打包到後台元件。

完整實作:衡量、拆解、最佳化、守護

今天的實作分四個動作。第一個動作是裝量測工具:@next/bundle-analyzer、lighthouse 桌面 CLI、web-vitals npm 套件。第二個動作是在 root layout 接入 web-vitals 量三個指標、把數據送到 Day 30 的 lib/monitor.ts。第三個動作是把幾個關鍵元件用 dynamic import 切開、把 next/image 套到主要圖片、把 route segment 的 cache 行為調對。第四個動作是在 CI 設定效能預算,超過就 fail。

第一步,安裝量測工具。Bundle analyzer 是 Next.js 官方整合,裝完只要改一行 next.config.ts 即可;web-vitals 是 Google 官方量測函式庫,體積極小(大約 1KB)。

# 安裝 2026 年 3 月主流版本
pnpm add -D @next/bundle-analyzer@^15.1.0 web-vitals@^4.2.4
pnpm add -D lighthouse@^12.2.0
# web-vitals 同時跑在 client 端(量真實使用者)與 build 端(CI 跑)

第二步,設定 next.config.ts 啟用 bundle analyzer。Next.js 15 的 withBundleAnalyzer 接受 analyzeServer 參數決定是否分析 server bundle。對 SSR 應用通常只分析 client bundle 就夠:

// next.config.ts
import withBundleAnalyzer from "@next/bundle-analyzer";

const bundleAnalyzer = withBundleAnalyzer({
  enabled: process.env.ANALYZE === "true",
  analyzeServer: false, // 只看 client bundle;server bundle 通常較小且穩定
});

const nextConfig = {
  reactStrictMode: true,
  experimental: {
    // 啟用 React 19 的新編譯器最佳化
    optimizePackageImports: ["lucide-react", "date-fns"],
  },
  images: {
    formats: ["image/avif", "image/webp"],
    remotePatterns: [
      { protocol: "https", hostname: "images.unsplash.com" },
      { protocol: "https", hostname: "cdn.hao-code.com" },
    ],
  },
};

export default bundleAnalyzer(nextConfig);

optimizePackageImports 是 React 19 與 Next.js 15 的最佳化重點:當某個元件庫(如 lucide-react、date-fns)提供大量獨立的 named exports 時,ESM tree-shaking 有時會因為副作用而把整包打包。Next.js 會自動把 import { Calendar } from "lucide-react" 改寫成 import Calendar from "lucide-react/dist/esm/icons/calendar",避免把整個圖示庫拉進來。我們把 lucide-react 與 date-fns 都列進來,這兩個是我們在 Day 33 服務頁、Day 34 表單頁、Day 35 後台頁大量使用的函式庫。

第三步,在 root layout 量 Core Web Vitals 並把數據送到監控層。這個元件是 client component,只負責量與送;送出後用 Sentry breadcrumb 或自製的 beacon endpoint 接:

// app/components/WebVitalsReporter.tsx
'use client';

import { useEffect } from 'react';
import { onLCP, onINP, onCLS, onFCP, onTTFB } from 'web-vitals';
import { monitor } from '@/lib/monitor';

export function WebVitalsReporter() {
  useEffect(() => {
    const send = (metric) => {
      monitor.captureMessage(`web-vital:${metric.name}`, 'info');
      // 對重要指標額外送結構化資料
      monitor.captureException?.(undefined, {
        extra: { name: metric.name, value: metric.value, rating: metric.rating, id: metric.id },
      });
      // 同時送 beacon(Day 41 部署時可以接 Vercel Analytics 或自製 endpoint)
      if (navigator.sendBeacon) {
        navigator.sendBeacon('/api/perf', JSON.stringify({
          name: metric.name, value: metric.value, rating: metric.rating, id: metric.id,
          ts: Date.now(), url: location.pathname,
        }));
      }
    };
    onLCP(send);
    onINP(send);
    onCLS(send);
    onFCP(send);
    onTTFB(send);
  }, []);
  return null;
}

把這個元件放在 root layout(app/layout.tsx)內,所有頁面都會自動量測。useEffect 確保只在 client 端執行;navigator.sendBeacon 是頁面關閉時也能送的請求,比 fetch 可靠。Day 41 部署到 Vercel 時可以改成送到 Vercel Analytics,零成本取得類似資料。今天先用自製 /api/perf 模擬,部署時再換。

第四步,把幾個會膨脹 bundle 的元件用 dynamic import 切開。最常見的目標是「只在特定頁面用、但被某個共用 layout 拉到」的元件,例如 Day 35 的後台圖表元件、Day 38 的登入 modal:

// app/admin/bookings/page.tsx(節錄:把圖表元件動態載入)
'use client';

import dynamic from 'next/dynamic';
import { BookingTable } from '@/components/admin/BookingTable';

// 圖表元件體積較大(200KB+),只在後台用,不該影響客戶端首頁
const BookingChart = dynamic(
  () => import('@/components/admin/BookingChart').then(m => m.BookingChart),
  { ssr: false, loading: () => <p>圖表載入中…</p> }
);

export default function AdminBookingsPage() {
  return (
    <div>
      <BookingTable />
      <BookingChart />
    </div>
  );
}

dynamic import 的關鍵是 ssr: false:這個元件只在 client 渲染,所以 Next.js 不會把它包進 SSR 的 HTML。對「需要瀏覽器 API 才能跑」的元件(Chart.js、Recharts、地圖元件)特別有用。注意 dynamic import 也會失去 tree-shaking 機會,所以要慎選目標:只切「大且不在首屏」的元件,不要無差別 dynamic。

第五步,把圖片改用 next/image 並設定 priority。我們在 Day 26 已經介紹過基本用法,今天把它對接到預約系統的具體元件:

// components/booking/ServiceCard.tsx
import Image from 'next/image';

export function ServiceCard({ service }) {
  return (
    <article className="rounded-lg border bg-white p-4 shadow-sm">
      <Image
        src={service.coverUrl}
        alt={service.name}
        width={400}
        height={240}
        sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 400px"
        priority={false}
        placeholder="blur"
        blurDataURL={service.blurDataURL ?? DEFAULT_BLUR}
        className="rounded-md"
      />
      <h3 className="mt-2 font-semibold">{service.name}</h3>
      <p className="text-sm text-slate-600">{service.description}</p>
      <p className="mt-2 text-lg font-bold text-indigo-600">NT$ {service.priceCents / 100}</p>
    </article>
  );
}

const DEFAULT_BLUR = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5gMcECoY8H8W1wAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAEklEQVQI12P4//8/AzbAxIAFjC5xAAAAAElFTkSuQmCC';

next/image 內建 AVIF/WebP 自動轉檔、響應式 sizes、placeholder="blur" 模糊預覽、priority 提前載入。第一張圖(首屏 LCP 元素)應該設 priority,其餘用 lazy load(預設)。我們的 coverUrl 指向 CDN 的虛構網址(https://cdn.hao-code.com/services/svc-001.jpg),真實部署時換成正式網址即可。

第六步,設定 route segment 的 cache 行為。Next.js 15 的 App Router 預設所有 fetch 都是 cache,但對「客戶登入後看到的個人資料」不該 cache。我們在每個 route 開頭宣告:

// app/bookings/page.tsx
import { cookies } from 'next/headers';

// 宣告這頁是動態(不要快取)
export const dynamic = 'force-dynamic';

export default async function MyBookingsPage() {
  const cookieStore = await cookies();
  const access = cookieStore.get('bf_access')?.value;
  const res = await fetch(`${process.env.API_BASE_URL}/bookings`, {
    headers: { Authorization: `Bearer ${access}` },
    cache: 'no-store', // 個人資料每次都打後端拿最新
  });
  // ...渲染
}

反過來,公開頁面(如 /services)可以走 ISR(Incremental Static Regeneration):

// app/services/page.tsx
// 公開頁面:每 60 秒重新生成一次
export const revalidate = 60;

export default async function ServicesPage() {
  const res = await fetch(`${process.env.API_BASE_URL}/services`, {
    next: { revalidate: 60, tags: ['services'] },
  });
  // ...渲染
}

這兩段展示了「同一個 fetch 在不同頁面有不同的 cache 策略」。公開頁面用 ISR 降低後端負擔,個人頁面用 force-dynamic 確保資料即時。Day 36 串接 FastAPI 後端時,這個設定會直接影響後端的 QPS:公開頁面每 60 秒才打一次後端,個人頁面每次都打。對一個中型預約系統,這可以省下 90% 的後端請求。

第七步,設定效能預算並寫成 CI 守護。我們用 Lighthouse 桌面 CLI 跑一次完整的量測,把 LCP、INP、CLS、總 bundle 大小寫進 perf-budget.json:

// perf-budget.json
{
  "lcpMs": 2500,
  "inpMs": 200,
  "cls": 0.1,
  "fcpMs": 1800,
  "ttfbMs": 600,
  "firstLoadJsKb": 180,
  "totalBundleKb": 500
}
# CI 跑的效能守護(節錄)
# 用 Lighthouse 桌面 CLI 量測正式 build,斷言預算
pnpm build
lighthouse http://localhost:3000 --preset=desktop --quiet --output=json --output-path=./lh.json
node scripts/check-perf.mjs ./lh.json ./perf-budget.json
# check-perf.mjs 會讀 LH 結果,比對預算;超標 process.exit(1)

這份 CI 在每次合併 PR 時跑,超過預算就 fail。預算值是「2026 年 3 月中型 SaaS 的合理門檻」,可以隨專案成熟再調。第一個月先寬鬆一點(例如 LCP 3 秒),等實際數據穩定再收緊。這套流程跟 Day 27 的 Playwright E2E 一起放在 CI,效能跟功能同樣被守護。

常見錯誤與踩雷

第一個常見錯誤是「只看 Lighthouse 跑分」。Lighthouse 給的是「實驗室數據」(simulated throttling、固定裝置),跟真實使用者的「田野數據」(field data)有落差。我們今天的 web-vitals 函式庫量的是真實使用者資料,但只在 production 環境才拿得到;本機開發只能看 Lighthouse 模擬值。要記得 Lighthouse 跑分高不代表真實使用者體驗好,反過來也成立。最佳實踐是兩者並看:Lighthouse 當 CI 預算守護、web-vitals 當真實資料觀察。

第二個常見錯誤是「dynamic import 過度使用」。每一個 dynamic() 都會產生獨立的 chunk,chunk 太多反而拖慢首屏(瀏覽器要發更多請求)。原則是:只切「大且不在首屏」的元件(通常是圖表、地圖、編輯器),不要為了「看起來比較模組化」就把所有元件都 dynamic。我們這次只切了一個 BookingChart,避免 chunk 爆炸。

第三個是「priority 設錯」。priority 應該只給首屏 LCP 元素(通常是 hero 圖、主標題區的圖片),不要全頁都 priority,否則 Next.js 把所有圖片都提前載入,反而搶頻寬讓真正重要的圖載更慢。我們的 ServiceCard 在首頁時 cover 是 LCP(設 priority),在清單內層就不該設(讓瀏覽器懶載入)。

第四個是「忘記設 sizes」。next/image 的響應式關鍵是 sizes 屬性:告訴瀏覽器在不同斷點下圖片實際顯示多大。如果不設,瀏覽器預設下載完整尺寸的圖(400×240 在行動裝置上其實只需要 360 寬),浪費頻寬。我們的範例寫了 sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 400px",在不同斷點用不同尺寸。

第五個是「route segment cache 設錯類型」。對「個人資料頁」設 revalidate=60 會讓使用者登出後的舊資料被快取 60 秒;對「公開服務頁」設 force-dynamic 會讓每次請求都打後端。我們今天的兩個範例展示了正確的對應,實際專案要依「資料是否個人、變動頻率」決定。

效能與實務提醒

今天的所有量測建議裝在 CI 而不是只在開發機跑。CI 跑 Lighthouse 的好處是「環境一致」:相同的硬體、相同的網路、相同的 Next.js build,量到的數字可以互相比較。開發機每台機器不同,跑出來的數字只能參考。GitHub Actions 提供的免費 runner 對小型 Next.js 專案足夠,跑完整 Lighthouse 大約 30–60 秒。

另一個實務提醒是「量測的時機」。Lighthouse 在每次程式碼改動後跑的成本不低(30 秒以上),所以建議只在「合併到 main 之前」跑一次當預算守護,而不是每次 commit 都跑。每次 commit 改用「快速 lint + typecheck + unit test」,預算守護留給 merge 階段。這跟我們 Day 40 會做的測試金字塔一致。

Server Component 的快取策略要小心。Next.js 15 的 fetch 在 Server Component 預設會被快取,但這個快取是「per request」的,跟頁面的 revalidate 設定互動。今天的 force-dynamic 範例刻意關閉所有快取,revalidate=60 範例則是 60 秒後重新生成。如果發現「明明改了後端資料前端卻沒更新」,第一個檢查點是這兩段設定。

web-vitals 的取樣率也是取捨參數。我們今天把 onLCP、onINP、onCLS 都開了(每個使用者都送一份),對中型流量網站(每日 10 萬次瀏覽)會產生 10 萬筆效能事件,送到監控層成本不低。實務上可以加上 10% 取樣:onLCP(send, { reportingDelay: 0, sampleRate: 0.1 })。但開發階段不要取樣,先把資料收齊再決定怎麼省。

小結

今天把預約管理系統前端做了一次完整的效能體檢。我們裝了 @next/bundle-analyzer 與 web-vitals、在 root layout 接入三個 Core Web Vitals 量測、把 BookingChart 用 dynamic import 切開、把封面圖改用 next/image 並設定 priority/sizes、為公開頁設 ISR 為個人頁設 force-dynamic、最後寫了效能預算與 CI 守護腳本。整套 stack 維持 Day 31–38 的共用設定,不引入新依賴。預期效果:首頁 First Load JS 從原本的 220KB 降到 130KB 左右、LCP 從 3 秒降到 1.8 秒、INP 從 350 毫秒降到 180 毫秒(具體數字依裝置與網路而異)。Day 40 我們會把這些畫面包進 Vitest + Playwright 的測試金字塔,並用同樣的預算邏輯設定 coverage 門檻。

結語

效能不是「加完即丟」的工作。今天做完量測與最佳化後,還要靠 Day 40 的測試覆蓋與 CI 預算守護,才能保證未來改版不會把今天做的一切抹掉。我們刻意把「衡量、拆解、最佳化、守護」拆成四個獨立段落,就是希望讀者能在每個段落停下來想想:「我目前卡在哪一層?下一步該做什麼?」明天,我們會把今天這些互動與畫面包進 Vitest 單元測試與 Playwright 端對端測試,並用 coverage 報告檢查「真的有測試覆蓋」這件事。

延伸資源

  • Next.js 15 效能官方文件(2026):https://nextjs.org/docs/app/building-your-application/optimizing,bundle analyzer、next/image、route segment 快取的標準寫法。
  • web-vitals 4.x 官方介紹(Google,2024):https://github.com/GoogleChrome/web-vitals,Core Web Vitals 量測函式庫的標準 API。
  • Core Web Vitals 官方定義(2024):https://web.dev/articles/vitals,LCP/INP/CLS 指標的完整定義與改善指南。
  • Lighthouse 12 桌面 CLI(2025):https://github.com/GoogleChrome/lighthouse#using-the-cli,CI 整合的標準做法。
  • Web 系列 Day 25 提到的 Pre-rendering:原文連結,FastAPI 後端的快取 header 設計參考。

留言

這個網誌中的熱門文章

Day 2 變數與資料型別

Day 2 變數與資料型別 引言 寫程式的過程中,變數與資料型別是處理資料的基礎。變數是存放資料的容器,資料型別則決定這筆資料有哪些特性、可以進行哪些操作。學會定義變數、認識各種資料型別,是學好 Python 的關鍵一步。 這篇文章會帶你了解 Python 中變數的觀念、如何定義變數,以及常見的資料型別,包括整數、浮點數、字串、布林值,還有串列、元組、字典與集合等容器型別。我們也會介紹變數的命名規則與撰寫風格建議,以及如何用 type() 檢查資料型別。 什麼是變數?如何在 Python 中定義變數 變數是在程式執行時用來存放資料的名稱。透過定義變數,我們可以給一筆資料一個名字,並在程式的其他地方用這個名字取用該筆資料。在 Python 中,變數不需要事先宣告型別,因為 Python 是動態型別語言,變數的型別由指定給它的值決定。 定義變數的基本語法 在 Python 中定義變數非常簡單,只要用賦值符號 = 把值指定給變數即可。例如: x = 5 # 定義變數 x,並把整數 5 賦值給它 name = "Alice" # 定義變數 name,並把字串 "Alice" 賦值給它 在這裡,x 是一個變數,被賦予整數 5;name 是另一個變數,被賦予字串 "Alice"。 變數的更新與覆寫 變數的值可以修改,也就是說,我們可以在程式的不同地方給同一個變數新的值。例如: x = 10 # x 最初被賦予 10 x = 15 # x 的值現在被更新為 15 這樣就能依照需求,在程式執行過程中靈活調整變數的值。 Python 的動態型別系統 Python 和某些靜態型別語言不同,定義變數時不需要宣告型別。賦值時,Python 會根據值自動判斷變數的型別。例如: x = 5 # x 是整數 x = 3.14 # x 變成浮點數 x = "Hi" # x 變成字串 同一個變數在程式執行過程中可以存放不同型別的值,這是 Python 的彈性之一。 常見資料型別 在 Python 中,資料型別決定我們可以對變數進行哪些操作...

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門 隨著人工智慧(AI)與深度學習(Deep Learning)快速發展,越來越多人對這些技術產生興趣。不論你是想踏入 AI 領域的初學者,還是已經有程式基礎的開發者,學好 Python 與深度學習框架(例如 PyTorch),都能為你打開更多可能。 為什麼選擇 Python? Python 已經是資料科學與人工智慧領域的首選語言。它的語法簡潔、容易上手,而且擁有龐大的生態系與大量開源函式庫。無論是資料處理、資料視覺化,還是建立機器學習與深度學習模型,Python 都能勝任。對想進入 AI 或資料科學領域的人來說,它幾乎是必備工具。 PyTorch 是什麼? PyTorch 是由 Meta(原 Facebook)AI 研究團隊開發的開源深度學習框架,以易用、靈活和動態計算圖著稱,是許多 AI 研究人員與開發者的首選。相較於其他框架,PyTorch 的寫法更貼近原生 Python,對初學者相對友善。無論是簡單的實驗,還是複雜的深度學習模型,PyTorch 都能提供強大的支援。 這個系列能帶給你什麼? 這個系列會從 Python 的基礎開始,帶你一步一步學習,最後能自己用 PyTorch 建立深度學習模型。即使你完全沒有寫過程式,也能跟著文章的節奏累積技能,理解 AI 與深度學習的核心觀念。 本系列涵蓋的主題 Python 基礎:從變數、條件判斷到函式與模組。 資料處理工具:用 NumPy 與 Pandas 有效率地操作資料。 資料視覺化:用 Matplotlib 與 Seaborn 把資料畫成圖表。 深度學習的數學基礎:線性代數、微積分與機率。 PyTorch 入門:理解張量、模型建構與 GPU 加速。 基礎深度學習模型:CNN 與 RNN 的實作應用。 深度學習專案實戰:從資料前處理到模型部署的端到端流程。 誰適合這個系列? 程式初學者 :如果你對 AI 充滿好奇,卻還沒寫過程式,系列的第一部分會帶你快速上手 Python,並幫助你理解深度學習的基本觀念。 資料科學愛好者 :如果你已經熟悉一些資料處理方法,進階部分會教你如何用 PyTorch 建構深度學習模型。 開發者與研究人員 :想更深入了...

Day 1 Python 簡介與環境設定

Day 1 Python 簡介與環境設定 引言 在現在的科技環境裡,程式設計已經是一項重要技能。無論你是對資料科學有興趣、想成為開發者,或是想踏入人工智慧(AI)領域,學會寫程式都能明顯提升你的競爭力。在眾多程式語言中,Python 因為語法簡單、功能強大、應用範圍廣泛,成為許多人進入程式世界的第一選擇。這篇文章會帶你認識 Python 的背景與優勢,並一步步教你在不同系統上安裝與設定 Python 開發環境,最後寫出第一支 Python 程式。 為什麼選擇 Python? Python 是一種高階程式語言,由 Guido van Rossum 在 1991 年發布。Python 的設計哲學強調程式碼的可讀性,並用縮排來定義程式區塊,這點和許多使用大括號的語言不同。簡潔的語法讓它成為初學者的理想選擇;就算是經驗豐富的開發者,也能用它完成複雜的專案。 Python 的優勢如下: 簡單易學 :Python 的語法清楚、結構簡潔,初學者很快就能上手。和其他語言相比,學習曲線相對平緩,不需要先弄懂一堆複雜觀念,就能開始寫程式。 應用範圍廣泛 :從資料科學、網頁開發、人工智慧、機器學習、自動化測試到網路爬蟲,Python 都有大量開源函式庫與工具支援,而且在這些領域都扮演關鍵角色。 豐富的函式庫與框架 :Python 的函式庫生態系非常龐大。做資料分析有 NumPy、Pandas;開發網站有 Django、Flask;做深度學習有 TensorFlow、PyTorch。各種需求幾乎都能找到對應的套件,讓開發更有效率。 跨平台支援 :Python 支援 Windows、macOS、Linux 等作業系統,程式通常不需要太多修改就能跨平台執行,讓開發與部署更有彈性。 活躍的社群 :Python 擁有龐大的開發者社群。學習或開發上遇到問題,幾乎都能在社群與論壇(例如 Stack Overflow)找到答案,對初學者來說是很強的後盾,也能減少卡關時的挫折感。 Python 的應用領域 Python 的流行與強大功能,讓許多領域都開始大量使用它。以下是幾個常見的應用方向: 資料科學 :隨著大數據與人工智慧興起,資料科學大量使用 Python。NumPy、Pandas 與 Matplotlib 等工具能處理和分析龐...