如何將 ts 集成到 node 項目中

為什么使用 TypeScript?

TypeScript 為 JavaScript 提供了可選的靜態(tài)類型。靜態(tài)類型的主要好處是在構(gòu)建時檢查和發(fā)現(xiàn)類型錯誤,所以代碼部署到生產(chǎn)環(huán)境后運行更穩(wěn)定。

環(huán)境準備

Node 版本 >= 16

初始化項目

mkdir node-ts
cd node-ts
npm init -y

安裝 typescript

npm i typescript -D

初始化 ts 配置文件

npx tsc --init

安裝 @tsconfig/node16

npm i @tsconfig/node16 -D

@tsconfig/node16 為 TypeScript 團隊為 Node.js v16 提供的基本配置。

tsconfig.json 中增加一下配置

{
  "extends": "@tsconfig/node16/tsconfig.json",
  "include": ["src"],
  "exclude": ["node_modules"]
}

編寫 ts 文件

src 下新建 index.ts 文件

const bar = 'bar'

console.log(bar)

通過 npx tsc 運行。js 文件是編譯出來了,但是控制臺報出錯誤:

TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.

發(fā)生此錯誤是因為在 tsconfig.json 配置文件和 @tsconfig/node16 的配置中 compilerOptions 沒有設(shè)置 lib 選項。該選項包含對象的類型定義和其他特定于瀏覽器的 API。將 "dom", "ESNext" 添加到 lib 中解決。但這不是 Node.js 項目的正確解決方案。正確的方式是安裝 Node API 的類型定義,使 TypeScript 編譯器可以理解和驗證所有內(nèi)置的 Node.js API。

安裝 @types/node

npm i @types/node -D

安裝完成后再次運行 npx tsc 錯誤消失。

如果要更改 js 文件的輸出位置,可以在文件中 tsconfig.json 中指定 outDir 選項,編譯后 js 文件將輸出到 dist 目錄下。

創(chuàng)建一個 http 服務(wù)感受下 ts 的類型檢查和提示:

// index.ts
import http from 'http'

const server = http.createServer((req, res) => {
  res.statusCode = 200
  res.setHeader('Content-Type', 'text/plain')
  res.end('hello ts node!')
})

server.listen(3000, () => {
  console.log('runing...')
})

因為 node 運行時不能直接 ts 文件,所以需要將 ts 文件編譯成 js 執(zhí)行。運行 npx tsc 然后 node dist/index.js,就可以訪問 http://localhost:3000/了。

這種方式每次改動代碼都要編譯,然后執(zhí)行 js 文件。

可以通過 tsc -w 監(jiān)聽文件的變化,然后使用nodemon工具監(jiān)聽js文件的變化。有點繁瑣。

使用 ts-node 直接執(zhí)行 ts 文件

通過 ts-node CLI 在直接執(zhí)行 ts 文件。安裝 ts-node

npm i ts-node -D

執(zhí)行 npx ts-node src/index.ts,完全可行。

ts-node 作為 ts 源碼 和 node 運行時之間的中間者。在執(zhí)行生成的 js 代碼之前轉(zhuǎn)譯源代碼。這種執(zhí)行速度更快。

另外 ts-node 啟用的功能是將現(xiàn)代 esm 語法轉(zhuǎn)換為 CommonJS 語法。這意味著在使用時 ts-node,您可以在代碼中通 import 而不是 require 使用 node 模塊。

package.json 中新增腳本:

{
  "scripts": {
    "dev": "ts-node src/index.ts"
  }
}

使用 tsc-node-dev 可以監(jiān)聽文件的變化,當文件內(nèi)容變化后重新編譯并運行。

{
  "scripts": {
    "dev": "ts-node-dev src/index.ts"
  }
}

ts 與第三方 npm 集成

當使用 npm 上的 node 模塊時,可能需要額外的配置才能編譯項目。

因為我們遇到的大多數(shù)模塊都是用 js 編寫的,因此 ts 無法確定方法的類型。模塊中的所有內(nèi)容都隱式為 any。

以 express 為例:

安裝 express

npm i express
import express from 'express'

const app = express()

app.get('/', function (req, res) {
  res.send('Hello World')
})

app.listen(3000)

會拋出錯誤: 無法找到模塊“express”的聲明文件,而且由于 tsconfig.json 的 strict 選項為 true,因此也啟用了 noImplicitAny 編譯器選項。使得 ts 在無法確定值的類型時會報錯而不是進行推斷類型。 所以 req 和 res 報錯。

可以為模塊提供類型聲明文件來修復此錯誤。DefinitiveTyped GitHub 上提供了許多流行的 npm 包的類型定義。通過 @types 作用域安裝包的類型定義。安裝 express 的類型定義文件:

npm install @types/express -D

再次運行 npx ts-node src/index.ts 就成功了。

這種方式無法實時監(jiān)聽文件的變化,可以使用 nodemon,通過 tsc -w 監(jiān)聽 ts 文件,變化后重新編譯成 js,nodemon 監(jiān)聽到 js 變化后重新執(zhí)行 js。

使用 ESLint 對 ts 進行檢查

安裝 ESLint

npm i eslint -D

要 eslint 對 ts 的檢驗,需要 eslint 的 ts 插件,@typescript-eslint/parser @typescript-eslint/eslint-plugin

npm i @typescript-eslint/parser @typescript-eslint/eslint-plugin -D

根目錄創(chuàng)建 .eslintrc.js 配置文件,配置內(nèi)容為:

module.exports = {
  env: {
    node: true,
    es2021: true
  },
  extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module'
  },
  plugins: ['@typescript-eslint']
}

package.json 中添加 lint 腳本:

{
  "scripts": {
    "lint": "eslint . --fix"
  }
}

代碼中新增:

let bar = 'bar'

console.log(bar)

執(zhí)行 npm run lint,let 改成 const,eslint 生效。

為了防止 ESLint dist 下的 js 文件檢查,創(chuàng)建 .eslintignore 文件,并將 dist 添加進去。因為 node_modules 文件夾中的所有內(nèi)容以及以點字符開頭的文件或文件夾(eslint 配置文件除外)都會被自動忽略,因此無需在 .eslintignore 文件中設(shè)置。

部署到生產(chǎn)環(huán)境

雖然 ts-node 在生產(chǎn)環(huán)境中使用也是是安全的。但為了減少服務(wù)器的啟動時間以及減少額外的內(nèi)存使用,最好預先編譯源文件。將編譯后的 js 部署到生產(chǎn)環(huán)境。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容