今天來為專案加上 TypeScript 設定,同時也會檢視目前為止的專案資料夾結構安排。
本文
設定 tsconfig.json
如果還沒安裝 TypeScript 的話可先在終端執行 yarn add -D typescript 來進行安裝。然後執行 node ./node_modules/typescript/bin/tsc --init 來建立 tsconfig.json。
其他建立方式可參考 Stack Overflow: How to install and run Typescript locally in npm?)。
因為是一次性的設定,所以個人沒有選擇在 package.json 中加入 scripts tsc。
以下是個人目前慣用的設定檔內容,基本上都是參考 React+TypeScript Cheatsheets 中的 Troubleshooting Handbook: tsconfig.json ,會使用比較嚴格的型別與變數使用狀況檢查,並加上 paths 設定。
compilerOptions 中的參數先分為上下兩半(文字值與布林),上半根據功能性、下半根據字母順序進行排列:
{ "compilerOptions": { "target": "es6", "lib": ["DOM", "ESNext"], "module": "esnext", "jsx": "react", "moduleResolution": "node", "paths": { "@Api/*": ["./src/api/*"], "@Asset/*": ["./src/asset/*"], "@Component/*": ["./src/component/*"], "@Hook/*": ["./src/hook/*"], "@Model/*": ["./src/model/*"], "@Reducer/*": ["./src/reducer/*"], "@Style/*": ["./src/style/*"], "@Tool/*": ["./src/tool/*"], "@/*": ["./*"] }, "allowJs": false, "allowSyntheticDefaultImports": true, "declaration": true, "esModuleInterop": true, "experimentalDecorators": true, "forceConsistentCasingInFileNames": true, "importHelpers": true, "incremental": true, "isolatedModules": true, "resolveJsonModule": true, "sourceMap": true, "strict": true, "noFallthroughCasesInSwitch": true, "noImplicitReturns": true, "noUnusedLocals": true, "noUnusedParameters": true }, "include": [ "./config/**/*", "./script/**/*", "./tool/**/*", "./src/**/*", "./src/env.d.ts" ], "exclude": ["./node_modules", "./build"]}真心推薦設定 paths,可以省去引用專案內檔案時,計算相對路徑的問題。且也能一眼就看出引用的是第三方套件、還是專案本身內的檔案:
// 第三方套件
// 專案內元件import TopNav from "@Component/common/TopNav";import dayjs from "dayjs";import React from "react";提醒:自定義 paths 後,連帶需要在 webpack 中設定 alias 才能順利打包,這會在後續介紹到專案 webpack 設定檔時說明。
想參考現成套件 tsconfig.json 設定的朋友也可以到 Centralized Recommendations for TSConfig bases 尋找資源。安裝後,透過 tsconfig.json 中的 extends 欄位即可借用其他人設定好的 ts 內容。
專案結構
不論是 side project 或是公司專案,個人通常會使用如下的資料夾結構:
.├── README.md├── config├── doc├── package.json├── public├── script├── src│ ├── api│ ├── asset│ ├── component│ │ ├── AppEntryPoint│ │ ├── Common│ │ ├── Layer│ │ ├── Layout│ │ └── Page│ ├── env.d.ts│ ├── hook│ ├── index.tsx│ ├── model│ ├── reducer│ ├── style│ └── tool├── tool├── tsconfig.json└── yarn.lock(可在終端輸入 tree -I node_modules -L 3 來得到資料夾結構樹,更多使用方式可參考 Stack Overflow: Linux command to print directory structure in the form of a tree)
各資料夾的目的說明如下:
README.md為專案的快速指南,通常會在這裡簡短說明專案概要、提供專案啟動腳本,如果此專案有更詳盡的操作手冊,則會將比較長篇的說明收納於./doc中./config用於存放 webpack 開發、打包用的設定內容;詳細的 webpack 設定會於日後文章解說./public負責收納 React app 專案的index.html模板與靜態檔案(包括但不限於faviconapple-touch-icon.pngrobots.txt等等)./script負責收納專案的啟動、打包腳本;更多關於這個資料夾的內容,會在鐵人賽後續文章中說明./src負責收納 React app 專案的核心內容apiassethook如其名稱描述,負責收納 api、靜態資源(字型、圖示等)與 react hook 內容component會再根據元件特性歸納到CommonLayerLayoutPage中(詳細的歸納判斷會於明天文章說明);AppEntryPoint內僅會有一個檔案,即是整個 React app 在./src/index.tsx中使用的入口env.d.ts負責提供 React app 的型別定義model收納 React app 會用到的純資料(例如常數、共用型別)以及 React Redux store 內容reducer收納 React Redux action/reducer 相關內容style負責收納 React app 的樣式檔案tool中是給 React app 專用的工具包,可能是 data formatter/transformer 或是 dayjs 函式
- 根目錄的
./tool負責收納專案用的工具,比如執行本機 webpack-dev 的start或打包用的build腳本
補充:
- 不論一個資料夾內會有幾份檔案,個人都習慣以單數名詞來為資料夾命名
- 專案間會盡量維持類似的資料夾結構,避免在維護不同專案時需要特別回想各個專案的檔案分類邏輯
以上結構歡迎參考。而如果有感覺奇怪、困惑,或是你認為有更好的分類方式,也非常歡迎留言討論唷 (`・∀・)
總結
本日重點回顧:想在專案內使用 TypeScript 但不想自己寫 tsconfig.json 的人可以到 Centralized Recommendations for TSConfig bases 尋找資源。另外,一套通用的專案資料夾結構,可以避免在維護多個專案時需要主動回想各類檔案的分類邏輯。