TypeScript 專案設定與開發流程

最近才開始用TypeScript開發,這篇文章記錄一下我做的設定,想要達成像是一般JavaScript的開發體驗,將所有TypeScript編譯的步驟自動化。

TypeScript 專案設定

以下會從零開始建立一個TypeScript專案,並且設定好所有的開發流程。

1. 初始化專案

使用npm init來初始化一個新的專案。

1
2
3
4
5
mkdir my-ts-project
cd my-ts-project
npm init -y
mkdir src
touch src/index.ts

2. 安裝 TypeScript 和 初始化 TypeScript 設定檔

安裝TypeScript,如果你不想要globally安裝,可以使用--save-dev的方式安裝。不過之後使用TypeScript的指令就要改成npx tsc

1
2
3
npm install -g typescript
# 或者
# npm install --save-dev typescript

接著初始化TypeScript的設定檔。我是globally安裝的,所以可以直接使用tsc指令來初始化。

1
tsc --init

此時會產生一個tsconfig.json的檔案,這個檔案是用來設定TypeScript的編譯設定。他有很多預設的設定,我大多也是沿用,只有一些微調,以下是所有沒有comment起來的
部分。詳細可以看 tsconfig reference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"compilerOptions": {
"target": "es2016",
"module": "NodeNext",
"rootDir": "src",
"moduleResolution": "NodeNext",
"sourceMap": true,
"outDir": "dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitAny": true,
"skipLibCheck": true
},
"include": [
"src/**/*"
]
}

3. 建立一個簡單的Express Server

安裝需要的套件,這裡我們需要安裝@types/node,因為我們要使用Node.js的一些API。
另外我們再安裝express。

1
2
3
npm install --save-dev @types/node
npm install express
npm install --save-dev @types/express

建立一個src/index.ts檔案,並且貼上以下程式碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
import express from 'express';
import { Request, Response } from 'express';

const app = express();
const port = 3000;

app.get('/', (req: Request, res: Response) => {
res.send('Hello World!');
});

app.listen(port, () => {
console.log(`Server started at http://localhost:${port}`);
});

這時候你的檔案結構應該是這樣的:

1
2
3
4
5
6
7
.
├── node_modules
├── package-lock.json
├── package.json
├── src
│ └── index.ts
└── tsconfig.json

試著執行tsc,你會發現dist資料夾被建立,裡面有index.jsindex.js.map

1
tsc

再執行node dist/index.js,你應該會看到Server started at http://localhost:3000,且在瀏覽器打開http://localhost:3000會看到Hello World!

到這裡已經建立好一個TypeScript的專案,並且可以正常運行。

設定開發流程

開發流程我們會希望有以下功能:

  1. 當我修改src/index.ts時,自動重新編譯。
  2. 當我修改src/index.ts時,自動重新啟動server。
  3. 可以根據環境變數來決定要使用哪一個設定檔。

1. 安裝套件

我們需要安裝nodemon來達成自動重新編譯和重新啟動server的功能。另外再安裝concurrently,這樣我們可以同時執行多個指令。

1
npm install --save-dev nodemon concurrently

2. 加入.env檔案

這邊我們會加入.env.development.env.production,分別是開發和正式環境的設定檔。這樣我們可以根據環境變數來決定要使用哪一個設定檔。你可以使用dotenv套件再根據NODE_ENV來讀取這些設定檔,不過這裡我們打算直接使用--env-file的方式來讀取。

1
2
3
4
5
6
touch .env.development
touch .env.production
echo "NODE_ENV=development" > .env.development
echo "PORT=3000" >> .env.development
echo "NODE_ENV=production" > .env.production
echo "PORT=8080" >> .env.production

我們也把src/index.ts的port部分改成以下程式碼,這樣我們可以根據環境變數來決定要使用哪一個設定檔。

1
const port = process.env.PORT || 3000;

2. 修改package.json

  • 加入prestart指令,在執行start之前會先刪除dist資料夾,再重新編譯。
  • 加入start指令,這是給正式環境使用的,會讀取.env.production的設定檔。且因為有prestart指令,所以會先重新編譯。
  • 加入watch:ts指令,這是給開發環境使用的,會監聽src資料夾的變化,並且重新編譯。
  • 加入dev指令,這是給開發環境使用的,會同時執行watch:tsnodemon,中間利用&來做到同時執行,缺點是其中一邊的output會蓋過另外一邊的output,這個可以透過concurrently解決,可以參考concurrently
  • 加入 `”type”: “module” 來使用 ESM 的方式來import module。

另外,nodemon也可以設定額外參數,例如--exec來指定要執行的指令,這樣我們就可以直接執行node,並且讀取.env.development的設定檔。也可以利用--watch dist來指定只要監聽dist的變化就好。除了command line參數,nodemon也可以透過nodemon.json來設定,這樣指令看起來會短一點,不過我喜歡把–exec的部分寫在package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"name": "my-ts-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc",
"prestart": "rm -rf dist && npm run build",
"start": "node --env-file=.env.production --enable-source-maps dist/index.js",
"watch:ts": "tsc -w",
"watch:node": "nodemon --exec node --env-file=.env.development --enable-source-maps dist/index.js",
"dev": "tsc && concurrently -k \"npm run watch:ts\" \"npm run watch:node\""
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.19.2"
},
"devDependencies": {
"nodemon": "^3.1.0"
}
}

執行專案

到這裡我們的開發流程已經設定好了,可以執行以下指令來開始開發。

1
npm run dev

執行結果:

如果到時候要用production環境執行或是寫Dockerfile,可以執行以下指令。

1
npm run start

執行結果:
可以看到port已經改成8080了。

作者

Yen-Ting Li

發表於

2024-04-19

更新於

2024-06-19

許可協議

評論