---
# System prepended metadata

title: 專案建構筆記
tags: [專案經驗]

---

## React 專案建構
### 一、安裝執行/開發輔助套件
- 建立 React with TypeScript 專案
  
  ::: info
  
  **npm init react-app** [project-name]
  (不能加 template 參數)
  
  或者
  
  **npx create-react-app** [project-name] <font color='red'>\-\-template typescript</font>
  
  範例與專案截圖: **npx create-react-app** my-app <font color='red'>\-\-template typescript</font>

  安裝最新套件:
  ![image](https://hackmd.io/_uploads/r17GEBywlg.png =70%x)

  :::
  
  :::success
  
  :bulb: cra 會安裝最新的 React 版本，若有 **指定版本** 需求，則於安裝後執行覆蓋安裝。
  
  以下為 React 指定為 v18 的指令：
  
  :::info
  npm i react@18.3.1 react-dom@18.3.1 @types/react@18.3.3 @types/react-dom@18.3.0 @testing-library/react@13.4.0 
  
  :::
  
  :::danger
  
  :bulb: **connected-react-router 已不支援 React v18**
  
  套件 connected-react-router 設計用來串接 redux 與 react router，支援 redux-thunk 與 redux-saga，原則上僅支援到 **React v17**，因為 React v18 搭配的 React Router Dom 為 v6，若仍要使用則需將 React Router Dom 降為 v5。
  
  React v18 以上版本可使用下列替代方案:
  - **redux-first-history**
    尚未用過
  - **redux-react-router**
  支援 React Redux v6 與 React Router v6 以上, 設定相關說明可參考 [官網](https://www.npmjs.com/package/@lagunovsky/redux-react-router) 連結，安裝指令如下:
    
    :::info
    npm i @lagunovsky/redux-react-router
    
  :::

- 新版 cra 相依套件的補充
![image](https://hackmd.io/_uploads/H1nuCelU0.png)

  ::: success
  **解法:**
  **npm i** \-\-save-dev @babel/plugin-proposal-private-property-in-object \-\-legacy-peer-deps

  :::
  
  ![image](https://hackmd.io/_uploads/rkVoy-g8C.png)


- 安裝開發輔助套件
  ::: info
  
  1. **安裝舊版 Eslint (<= v7)**
      - <font color='blue'>[6.8.0 => es6, 2018] (兆豐案)</font>
        - **npm i** eslint@6.8.0 -D 
        - **npx** eslint@6.8.0 \-\-init (生成 .eslintrc.json)
        - **npm i** babel-eslint -D
     - <font color='blue'>[7.32.0 => es2021, 2020] (臺銀案)</font>
       - **npm i** eslint@7.32.0 -D 
       - **npx** eslint@7.32.0 \-\-init (生成 .eslintrc.json)
       - **npm i** babel-eslint -D
     - **eslint-plugin、parser** 降版至 v4.0.0（移除後重新安裝），否則會**無法編譯**
  ![image](https://hackmd.io/_uploads/SyzmfPb8C.png)
  
  2. **安裝專案需要的語法規則套件**
     **npm i** eslint-config-standard@16.0.0 eslint-config-standard-jsx@10.0.0 eslint-config-standard-react@11.0.0 -D
     <font color='red'>**"extends":**</font> [
     &nbsp;&nbsp;...
     &nbsp;&nbsp;**"react-app"**,
     &nbsp;&nbsp;**"standard-react"**,
     &nbsp;&nbsp;...
     ],
     **npm i** eslint-plugin-flowtype@5.2.0 eslint-plugin-import@2.25.4 eslint-plugin-node@11.1.0 eslint-plugin-promise@5.2.0 eslint-plugin-react@7.28.0 eslint-plugin-react-hooks@4.3.0 -D
     <font color='red'>**"plugins":**</font> [
     &nbsp;&nbsp;...
     &nbsp;&nbsp;**"react"**,
     &nbsp;&nbsp;**"react-hooks"**,
     &nbsp;&nbsp;**"@typescript-eslint"**,
     &nbsp;&nbsp;**"import"**,
     &nbsp;&nbsp;...
     ],<br>
  3. **覆寫共用規則**
  <font color='red'>**"rules":**</font> {
  &nbsp;&nbsp;**"react/prop-types"**: "off",
  &nbsp;&nbsp;**"react-hooks/rules-of-hooks"**: "error",
  &nbsp;&nbsp;**"react-hooks/exhaustive-deps"**: "warn",
  &nbsp;&nbsp;**"@typescript-eslint/type-annotation-spacing"**: "error",
  &nbsp;&nbsp;**"@typescript-eslint/no-unused-vars"**: "error",
  &nbsp;&nbsp;**"import/no-anonymous-default-export"**: "off",
  &nbsp;&nbsp;**"jsx-quotes"**: [
  &nbsp;&nbsp;&nbsp;&nbsp;"error",
  &nbsp;&nbsp;&nbsp;&nbsp;"prefer-double"
  &nbsp;&nbsp;],
  &nbsp;&nbsp;**"semi"**: [
  &nbsp;&nbsp;&nbsp;&nbsp;"error",
  &nbsp;&nbsp;&nbsp;&nbsp;"always"
  &nbsp;&nbsp;]
  }
  
  4. 套件列表
  ![image](https://hackmd.io/_uploads/HJ0MBdbIC.png)

  :::
  
  ::: info
  
  :bulb: **ESlint v8.57.0 安裝步驟** (搭配 Node v18.20.4 + React v18.3.1)
  1. **ESLint 套件、ES2015+ (ES6+) 匯出/匯入語法套件**
  npm i eslint@8.57.0 @eslint/js@9.5.0 globals@15.6.0 eslint-plugin-import@2.29.1 -D
  
  2. **Typescript 語法規則套件**
  npm i typescript-eslint@7.13.1 @typescript-eslint/parser@7.14.1 -D
  
  3. **React 語法規則套件**
  npm i eslint-plugin-react@7.34.3 eslint-plugin-react-hooks@4.6.2 -D
  
  4. **建立設定檔並調整語法規則**
  新增 eslint.config.mjs 檔案並加入各類規則，請參考 [設定內容](https://hackmd.io/@HolyCho/SyW60UMPlx)
  
  :::
  
  ::: danger
  :bulb: ESLint 導覽安裝指令: **npx eslint \-\-init**
    - 安裝時會有問答引導
    - 根據使用者需求於過程中會追加安裝: eslint @eslint/js globals typescript-eslint eslint-plugin-react
    - 新版最後會生成設定檔: .eslint.config.mjs

    :question: 安裝問題: 安裝指令 \-\-init 生成的設定檔，於重啟 VS Code 後似乎無法正常生效。
    :star: <font color='ligreen'>**若是手動安裝 eslint @eslint/js globals typescript-eslint eslint-plugin-react 套件並自行建置 .mjs 檔，於重啟 VS Code 後正常檢查語法。**</font>
    
  :::
  
  ::: warning
  
  :bulb: 新版 ESlint 所有配置（**eslint.config.mjs**）於變更完成後，需<font color='red'>**重啟** VS Code 方可生效</font>。(否則不會生效)
  
  :::

### 二、調整目錄 src/app
- **bff**
  :::info
    :bulb: **放置前端 API 服務與相關服務**
    1. enums: API 所需的列舉
    2. models: API 所需的資料定義
    3. services: API 呼叫
  :::

- **common**
   :::info
     :bulb: **放置共用切版模板與小組件**
     1. layouts: 排版
     2. components: 頁面所需之各類小組件
   :::

- **core**
   :::info
     :bulb: **放置各種自訂頁面工具，如自訂燈箱、自訂 Hook、檢核規則、各類轉換公式**
     1. enums: 前端頁面所需的列舉
     2. hooks: 前端頁面所需自定義鉤子
     3. models: 前端頁面所需的列舉映射
     4. router
        - guards: 卡控路由之守衛
        - path: 全站路由列表、名稱轉換(會員足跡)
        - service: 處理動態路由之工具
        - types: 定義動態路由之相關參數
     5. services
        - commonService: 共用工具
        - cookieService: 操作 universal-cookie 之 Cookie
        - dialogService: 提示視窗
        - storageService: 針對 localStorage、sessionStorage、cookieService 操作
   :::

- **features**
   :::info
   :bulb: **放置產品/專案功能頁，透過前端路由規則映射並掛載**
     1. Activity：最新消息、熱門活動
     2. Home：主首頁
     3. Member：會員中心
     4. Insure：各險種之投保流程
     5. Service：各項服務頁面
   :::

- **store**
   :::info
   :bulb: **放置 redux 函式庫於架構內協作的程式碼、狀態、界面定義等，如 action、reducer、saga、store（可對照 features 結構，以利維護與開發）**
     1. activity: 存放最新消息、熱門活動等資料
     2. home: 存放主首頁資料
     3. member: 存放會員資料
     4. insure: 存放投保流程資料
     5. service: 存放服務資料
     6. system/ui/...等(不屬於 features 範疇內可視需求建構)
   :::

### 三、建立目錄 src/assets
- **css**: 各頁面與組件編譯後之樣式
- **img**: 頁面所需圖片
- **scss**: 各頁面與組件所引用的 Sass/SCSS 檔案

### 四、建立目錄 src/environments
編譯環境設定，如 SIT、UAT、PROD 等
- **sit 環境檔**: environment.development.ts
- **uat/prod 環境檔**: environment.production.ts

### 五、測試套件錯誤
- 若發生 **「Environment key "jest/globals" is unknown」** 錯誤，則需安裝測試套件，安裝指令如下:

  :::info
  npm i eslint-plugin-jest -D
  :::

- 設定檔 **eslint.config.mjs** 加入設定:
  ```
  {
    "plugins": ["jest"],
    "env": {
      "jest/globals": true
    },
  }
  ```
- 經測試，若是 Nodejs v18 環境下執行 npm start 不會發生此錯誤

### 六、其他注意事項
- tsconfig.json 編譯選項 (compilerOptions) 需加上 baseUrl 設定作為編譯的根目錄
  ![image](https://hackmd.io/_uploads/HyqACxqvxg.png =50%x)

- 需調整 public/index.html 內的 id 需與 index.tsx 內一致，下面以 insure-app 作為識別 id
  檔案 **public/index.html**
  ![image](https://hackmd.io/_uploads/rJPJRlqwxl.png)
  檔案 **index.tsx**
  ![image](https://hackmd.io/_uploads/HJ3KaeqPle.png =50%x)
  
- 若於安裝過程中發生套件版本衝突，可用指令 **\-\-legacy-peer-deps**，範例如下:
  :::info
  npm i connected-react-router@6.9.3 **\-\-legacy-peer-deps**
  :::

