---
# System prepended metadata

title: NPM 安裝以及 React Project 演練

---

# NPM 安裝以及 React Project 演練
> 目標：帶你從 **安裝 Node.js/npm** → **理解 ES Module（import/export）** → **建立 React 專案** → **切分組件與加入樣式**。同時提供 **Vite（推薦）** 與 **Create React App（舊方案）** 兩條路線，以及常見安裝錯誤排除。

---

## 一、從安裝 Node.js 開始

**Node.js** 是瀏覽器外的 JavaScript 執行環境，常見於後端（如 Express）與建置工具（打包、測試、Lint 等）。安裝 Node 時會附帶 **npm（Node Package Manager）**，用來安裝/管理套件與執行專案腳本。

### 1. 安裝 Node.js（建議 LTS 版本）

* 前往官方網站下載安裝程式：[https://nodejs.org](https://nodejs.org)
* 安裝完成後在終端機驗證：

```bash
node -v   # 顯示 Node 版本
npm -v    # 顯示 npm 版本
```

### 2. 版本管理（選用，但強烈建議）

不同專案可能需要不同 Node 版本，建議安裝版本管理器：

* macOS/Linux：`nvm` 或 `fnm`
* Windows：`nvm-windows` 或 `fnm`

有了版本管理器後，可以輕鬆切換：

```bash
nvm install --lts
nvm use --lts
```

> 有 `yarn`、`pnpm` 等替代方案；本講義以 **npm** 為主，指令可類推。

<br/>

## 二、JavaScript 的 `import` 與 `export`

ES Module 讓程式可模組化、可重用、好維護。

### Export（導出）

**命名導出**：

```js
export const A = 1;
export function greet(name) { return `Hi, ${name}`; }
```

**預設導出**（一個模組僅一個 default）：

```js
const PI = 3.14159;
export default PI;
```

### Import（導入）

**命名導入**：

```js
import { A, greet } from './utils.js';
```

**預設導入**：

```js
import PI from './constants.js';
```

**整包導入**：

```js
import * as math from './math.js';
```

> 注意：ESM 天生嚴格模式；導入值為唯讀（但若為物件其內容仍可變動）。

<br/>

## 三、建立並啟動 React 專案

> 2025 年的實務建議：**優先用 Vite 或 Next.js**；`create-react-app`（CRA）已停更多年，仍可用於學習，但不建議新專案採用。

### 路線 A：使用 Vite（推薦）

1. 建立專案：

```bash
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
```

2. 重要檔案結構：

```
my-react-app/
├─ index.html
├─ package.json
├─ vite.config.ts (或 .js)
└─ src/
   ├─ App.jsx
   └─ main.jsx
```

3. 入口檔（Vite 預設）：

```jsx
// src/main.jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)
```

```jsx
// src/App.jsx
export default function App() {
  return <div>Hello React (Vite)</div>
}
```

### 路線 B：Create React App（教學/舊方案）

```bash
npx create-react-app my-app
cd my-app
npm start
```

**CRA 典型結構**：

```
my-app/
├─ public/index.html
├─ src/index.js
├─ src/App.js
└─ package.json
```

**React 18 匯入要點**：React 18 之後需從 `react-dom/client` 匯入 `createRoot`：

```jsx
// src/index.js (React 18 正確寫法)
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)
```

> 你原文提到「不需要加 /client」是 **React 17 舊寫法**。若使用 React 18，請務必用 `react-dom/client`。

<br/>

## 四、最少檔案的 React 專案（以 CRA 流程示意）

> 目標：用最少檔案跑起來，理解每個檔案的責任。

**檔案結構**

```
- src
    index.js
- public
    index.html
package.json
```

**package.json（CRA 範例）**

```json
{
  "name": "my-react-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-scripts": "5.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

```

**public/index.html**

```html
<!DOCTYPE html>
<html lang="zh-Hant">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
```

**src/index.js**

```jsx
import React from 'react'
import ReactDOM from 'react-dom/client'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <div>Hello React</div>
  </React.StrictMode>
)
```

[程式範本](https://github.com/IffyArt/2025-fullstack-course-forntend/tree/feature/react-basic-project)

<br/>

## 五、把 `App.js` 獨立並渲染到首頁

**目錄**

```
- src
    App.js
    index.js
- public
    index.html
```

**src/App.js**

```jsx
export default function App() {
  return <div>Hello React, I am App.js</div>
}
```

**src/index.js（React 18）**

```jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)
```

> 分檔的目的：`index.js` 專注「掛載/啟動」，`App.js` 專注「畫面與邏輯」。可讀性與維護性更好。

<br/>

## 六、切分元件（Components）

**目錄**

```
- src
    - components
        Header.jsx
    App.js
    index.js
```

**src/components/Header.jsx**

```jsx
const Header = () => (
  <header>
    <h1>Welcome to My Website</h1>
  </header>
)
export default Header
```

**src/App.js**

```jsx
import Header from './components/Header'

export default function App() {
  return (
    <>
      <Header />
      Hello React, I am App.js
    </>
  )
}
```

> `<>...</>` 是 `React.Fragment` 的語法糖：不多包一層多餘的 `<div>`。

<br/>

## 七、加入樣式（CSS / 外部資源）

**目錄**

```
- src
    - components
        Header.jsx
    - styles
        style.css
    App.js
    index.js
```

**src/styles/style.css**

```css
.header {
  background-color: #333;
  color: white;
  padding: 1rem;
  text-align: center;
  height: 200px;
}
```

**src/components/Header.jsx**

```jsx
const Header = () => (
  <header className="header">
    <h1>Welcome to My Website</h1>
  </header>
)
export default Header
```

**src/App.js**

```jsx
import Header from './components/Header'
import './styles/style.css'

export default function App() {
  return (
    <div>
      <Header />
      Hello React, I am App.js
    </div>
  )
}
```

> 在 JSX 內用 **`className`** 取代 `class`。

### 外部資源（以 Bootstrap、Google Icons 為例）

在 `public/index.html` 直接引入最快：

```html
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
```

範例（`App.js`）

```jsx
import Header from './components/Header'
import './styles/style.css'

export default function App() {
  return (
    <div>
      <Header />
      <div className="btn-group" role="group" aria-label="Basic mixed styles example">
        <span className="material-symbols-outlined">logout</span>
        <button type="button" className="btn btn-danger">Left</button>
        <button type="button" className="btn btn-warning">Middle</button>
        <button type="button" className="btn btn-success">Right</button>
      </div>
    </div>
  )
}
```

<br/>

## 八、常見安裝/啟動錯誤排除

### 1) Windows 執行 `npx` 出現找不到 Roaming/npm 目錄

```text
npm ERR! enoent ENOENT: no such file or directory, lstat 'C:\\Users\\User\\AppData\\Roaming\\npm'
```

**解法**（以 CMD）：

```bat
mkdir %USERPROFILE%\AppData\Roaming\npm
```

### 2) 連不上 Registry / 權限問題

* 確認網路與代理；或切換 registry：

```bash
npm config set registry https://registry.npmmirror.com
# 或
npm config set registry https://registry.npmjs.org
```

* 權限錯誤請避免用系統管理員身分安裝全域套件；或改用版本管理器。

### 3) React 版本對應 `react-dom` 匯入

* **React 18**：`import ReactDOM from 'react-dom/client'` + `createRoot(...)`
* **React 17**（舊）：`import ReactDOM from 'react-dom'` + `ReactDOM.render(...)`
