The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何快速建置一個 Node.js 專案並使用 TypeScript 與 VSCode 進行開發

每次要開始寫一個 Node.js 搭配 TypeScript 的專案,都沒有一個能讓自己滿意的專案範本,不然就是網路上經常找到不完整的參考文件。這篇文章我打算建立一個 Node.js 搭配 TypeScript 進行開發的專案範本,完整交代整個建置過程,並用一個簡單的例子說明開發與執行的注意事項。

TL;DR (Too Long; Don't Read)

如果你是個大忙人,可以直接使用我寫好的專案範本,跳過以下所有內容:

  1. 使用 .NET CLI 命令列工具,安裝我寫好的專案範本

    dotnet new --install Duotify.Templates.DotNetNew
    
  2. 使用 dotnet new tsnode 建立專案範本並執行 npm install 安裝 npm 套件

    mkdir punycode-converter && cd punycode-converter
    dotnet new tsnode -c "Will 保哥"
    npm install
    
  3. 開啟 Visual Studio Code 並對 src/app.ts 檔案進行開發

    code .
    
  4. 按下 Ctrl+Shift+B 即可自動執行 npm start 命令

    程式會自動監視檔案變更並自動重啟程式!

準備 Windows 命令列環境

要準備好一個 Node.js 與 TypeScript 的開發環境,你大致需要以下工具:

  1. Node.js

  2. PowerShell Core (在 Windows 唯一推薦的命令列工作環境)

    事實上 PowerShell Core 是跨平台的 Shell 環境,只是 Linux 使用者很少人用

  3. UnxUtils (常用的 GNU utilities 工具)

  4. curl (模擬 HTTP 命令與下載檔案的好工具)

  5. jq (一個專門用來操作 JSON 資料的強大工具)

以下可以用單一命令將環境全部自動裝好:

choco install nodejs-lts powershell-core unxutils curl jq -y

建立 Node.js with TypeScript 專案範本

以下命令同時可以相容於 Linux Shell 與 PowerShell Core 執行環境:

請不要用 Command Prompt 或 Windows 內建的 PowerShell 來執行以下程式碼,使用上地雷太多了,不但使用 Pipe 的時候可能會有檔案編碼問題,命令的輸入方式還無法跨平台相容。以下命令我測試過無數次,可完美相容於於 Linux, macOS 常見的 Shell 環境,請記得額外安裝 curljq 工具即可!👍

mkdir punycode-converter
cd punycode-converter

npm init -y
npx typescript --init
npx tslint --init

echo 'loglevel=silent' > .npmrc

npm install typescript @types/node tslint nodemon ts-node --save-dev

npx strip-json-comments-cli tsconfig.json | jq '.' | npx sponge tsconfig.json
jq --arg     'outDir' './dist' '.compilerOptions.outDir = $outDir' tsconfig.json | npx sponge tsconfig.json
jq --argjson 'strict' 'false'  '.compilerOptions.strict = $strict' tsconfig.json | npx sponge tsconfig.json

jq --arg 'severity' 'warning' '.defaultSeverity = $severity' tslint.json | npx sponge tslint.json

curl -s https://www.toptal.com/developers/gitignore/api/node > .gitignore

npx node-editorconfig

jq 'del(.scripts.test)' package.json | npx sponge package.json

jq --arg cmd 'nodemon src/app.ts'      '.scripts.start = $cmd' package.json | npx sponge package.json
jq --arg cmd 'tsc'                     '.scripts.build = $cmd' package.json | npx sponge package.json
jq --arg cmd 'tsc && node dist/app.js' '.scripts.node  = $cmd' package.json | npx sponge package.json

mkdir src
touch src/app.ts

npm start

詳細解釋建立 Node.js with TypeScript 專案範本的過程

  1. 建立專案

    請注意目錄名稱的命名規則必須符合 npm 套件名稱的命名規範

    • 套件名稱總長度不得超過 214 字元
    • 套件名稱不能有任何英文大寫字元
    • 套件名稱不能違反 URL 可用字元的規則

    簡單來說,建議都用小寫字元([a-z])與減號(-)就好!

    mkdir punycode-converter
    cd punycode-converter
    

    如果專案不會發布到 npm registry 的話,那麼 name 是什麼其實不重要!

  2. 初始化 package.json 檔案

    npm init -y
    echo 'loglevel=silent' > .npmrc
    

    我設定 loglevel=silent.npmrc 的目的是不希望 npm start 的時候看到一堆沒用的 log 訊息!

  3. 安裝 TypeScript 必備的 npm 套件

    npm install typescript @types/node tslint nodemon ts-node --save-dev
    

    套件 typescript 為 TypeScript 編譯器本身。套件 @types/node 是 Nodejs 的 TypeScript 型別定義檔(declaration file)。套件 tslint 則是 TypeScript 的 Linting 工具,檢查各種 TypeScript 寫作風格。nodemon 用來監控程式碼變更,自動重新執行 Node.js 程式。ts-node 用來直接執行 *.ts 程式,省去手動執行 tsc 編譯的過程。

  4. 初始化 tsconfig.json 設定檔

    這個 tsconfig.json 設定檔主要用來幫助 TypeScript 編譯器判斷該如何編譯我們的專案。

    npx typescript --init
    

    tsconfig.json 檔案中包含的大量註解,這些註解極具參考價值,但你可以視情況清除這些註解。

    npx strip-json-comments-cli tsconfig.json | jq '.' | npx sponge tsconfig.json
    

    初始化 tsconfig.json 之後,我會修改 tsconfig.jsoncompilerOptions.outDir 屬性,讓 TypeScript 編譯好的結果輸出到 ./dist 目錄。

    jq --arg 'outDir' './dist' '.compilerOptions.outDir = $outDir' tsconfig.json | npx sponge tsconfig.json
    

    由於 tsconfig.json 預設採用「嚴格型別檢查」功能,有時候我會把 tsconfig.jsoncompilerOptions.strict 設定為 false,以免型別檢查太過嚴格影響開發體驗! XD

    jq --argjson 'strict' 'false' '.compilerOptions.strict = $strict' tsconfig.json | npx sponge tsconfig.json
    
  5. 初始化 tslint.json 設定檔

    npx tslint --init
    

    你可以考慮設定 TSLint 檢查出來的問題標示為「警告」而非「錯誤」!

    jq --arg 'severity' 'warning' '.defaultSeverity = $severity' tslint.json | npx sponge tslint.json
    
  6. 初始化 .gitignore 設定檔 (gitignore.io)

    curl -s https://www.toptal.com/developers/gitignore/api/node > .gitignore
    
  7. 初始化 .editorconfig 編輯器設定檔 (node-editorconfig)

    npx node-editorconfig
    
  8. 修改 package.jsonscripts 區段,增加一個 npm start 的執行命令

    有個 scripts.test 屬性只是個範例,必要時可刪除:

    jq 'del(.scripts.test)' package.json | npx sponge package.json
    

    設定執行 tsc 會自動編譯專案目錄下所有 *.ts 檔案並輸出到 dist/ 目錄,接著直接透過 node 啟動該程式!

    jq --arg var 'tsc && node dist/app.js' '.scripts.start = $var' package.json | npx sponge package.json
    

    修改之後 packages.jsonscripts 區段會變成以下內容:

    "scripts": {
      "start": "tsc && node dist/app.js"
    },
    
  9. 改用 nodemon 啟動程式

    每次啟動 Node.js 程式都要執行一次 npm start 其實有點不太方便,因為在開發時期一直在更新程式碼,我們的程式需要不斷頻繁的重新啟動。

    此時最好的方法,就是有個工具可以不斷監視資料夾中是否有原始碼更新,只要有檔案異動,就自動重新啟動 Node.js 程式,此時就是 nodemonts-node 上場的時候!當你用 nodemon 執行一個 *.ts 程式,他在內部就會自動使用 ts-node 自動編譯這些程式,並自動透過 node 執行起來,當有程式異動存檔,也會自動重啟程式,非常方便!

    jq --arg cmd 'nodemon src/app.ts'      '.scripts.start = $cmd' package.json | npx sponge package.json
    jq --arg cmd 'tsc'                     '.scripts.build = $cmd' package.json | npx sponge package.json
    jq --arg cmd 'tsc && node dist/app.js' '.scripts.node  = $cmd' package.json | npx sponge package.json
    

    所以我們的 packages.jsonscripts 區段,就會變成以下內容:

    "scripts": {
      "start": "nodemon src/app.ts",
      "build": "tsc",
      "node": "tsc && node dist/app.js"
    },
    
  10. 建立主程式的原始碼資料夾

    mkdir src
    touch src/app.ts
    
  11. 加入 Visual Studio Code 的 .vscode/tasks.json 工作定義檔

    以下定義檔可以讓你按下 Ctrl+Shift+B 就會自動執行 npm start 命令,非常便利!

    {
        "version": "2.0.0",
        "tasks": [
            {
                "label": "npm start",
                "type": "shell",
                "command": "npm start",
    
                "group": {
                    "kind": "build",
                    "isDefault": true
                },
                "presentation": {
                    "showReuseMessage": false,
                    "reveal": "always",
                    "clear": true,
                    "focus": true
                }
            }
        ]
    }
    

開發一段簡短的 Node.js 程式

我打算建立一個 Punycode (國際化域名編碼) 的轉換工具,讓你可將任意 Punycode 轉成 Unicode 字元,或是將 Unicode 字元轉成 Punycode 編碼。

  1. 安裝會用到的套件與 TypeScript 型別定義檔

    這裡我們會使用 Punycode.js 模組來完成這個應用程式。

    npm install punycode --save
    npm i @types/punycode --save-dev
    
    npm install express@4.17 --save
    npm install @types/express@4.17 --save-dev
    

    你可以到 TypeScript: Search for typed packages 搜尋上萬個現成的 TypeScript 型別定義檔

  2. 正確的在 src/app.ts 載入強型別的模組

    一般 Node.js 程式都是用以下方式匯入 CommonJS 模組

    const punycode = require('punycode/');
    

    但是在 TypeScript 要換用 import 的方式匯入模組才能參考到正確的型別

    import punycode = require('punycode/');
    

    另外用 ESM (ES Modules) 語法也是可以的

    import * as punycode from 'punycode/';
    

    punycode

    備註:上述範例你看到我匯入的模組名稱是 punycode/,各位可能會覺得有點奇怪,其實是因為 punycode 模組一直都是 Node.js 內建的模組,但是從 v7.0.0 以來,就一直處於 Deprecated (退役) 狀態,官方是說遲早有一天會從 Node.js 中移除,但是至今都尚未移除。短時間內只能透過在名稱後面加上 / 當作暫時的緩解措施(Workaround),否則你會看到如下圖的訊息提示: 2021-07-18_21-05-07

  3. 只要能正確匯入模組,撰寫程式的時候就可以享受 IntelliSense 提示與型別檢查

    console.log(punycode.version);
    console.log(punycode.toUnicode('xn--cssyd'));
    console.log(punycode.toASCII('多奇'));
    

    function punycode.toUnicode(input: string): string

  4. 執行程式

    npm start
    

    在 Visual Studio Code 中可以按下 Ctrl+Shift+B 快速鍵,就可以直接啟動程式

  5. 開發一段簡短的 Express 程式

    請在 src/app.ts 填入以下程式碼,過程中可以發現每個變數都有完整的型別標示

    import punycode = require('punycode/');
    import express from 'express';
    
    const app = express();
    const port = 3000;
    
    // http://localhost:3000/toUnicode?str=xn--cssyd
    app.get('/toUnicode', (req, res) => {
        res.send(punycode.toUnicode(req.query['str'].toString()));
    });
    
    // http://localhost:3000/toASCII?str=多奇
    app.get('/toASCII', (req, res) => {
        res.send(punycode.toASCII(req.query['str'].toString()));
    });
    
    app.listen(port, () => {
        console.log(`server is listening on ${port}`);
    });
    

    res.send(punycode.toASCII(req.query['str'].toString()));

    在 Visual Studio Code 中可以按下 Ctrl+Shift+B 快速鍵,就可以直接啟動程式。啟動後 nodemon 會自動監視資料夾下的檔案變更,有檔案儲存就會自動重啟程式!

完整的範例程式

https://github.com/doggy8088/punycode-converter

相關連結

留言評論