使用typescript搭建express
开始
为这个项目创建一个新的目录,使用下面的命令初始化项目并创建一个包。
NPM init -y
初始化后,让我们安装必要的包
npm i express dotenv cors helmet body-parser
在express中配置typescript
npm i -D typescript @types/node @types/express @types/dotenv @types/cors @types/helmet
现在我们要在我们的目录中生成 tsconfig.json 文件。使用下面的命令:
npx tsc --init
打开 tsconfig.json 文件,注释掉 compilerOptions 中的所有字段,并配置 baseUrl 和 outDir
接下来,让我们创建一个 .env 文件,定义所有敏感变量的。
创建.env文件
port=5000
创建 index.ts 文件
然后创建一个 src 文件夹,在该文件夹下创建一个 index.ts 文件,此时目录结构如下所示:
之后我们就在 index.ts 文件中开始编写我们的代码。
import * as dotenv from 'dotenv'
import express from 'express'
import cors from 'cors'
import helmet from 'helmet'// 变量
dotenv.config()const app = express(); // 使用中间件
app.use(helmet());
app.use(cors());
app.use(express.json())module.exports = app
现在在 src 目录下创建一个 server.ts 文件。
server.ts
require("dotenv").config();
const app = require(".")const PORT = process.env.PORT || 3000
app.listen(PORT, async () => {console.log(`listning on port ${PORT}`)
})
现在我们必须配置我们的开发脚本,我们正在使用的另一个与开发相关的工具是 nodemon,只要文件有变化,就重新启动我们的应用程序或服务器。
此时我们还得安装一个 ts-node 执行引擎。
npm i -D nodemon ts-node
然后在目录中配置一个 nodemon.json 文件。
nodemon.json
{"watch" : ["src", ".env" ], "ext":"js,ts,json", "ignore": ["src/logs/*", "src/**/*.{spec,test}.ts"], "exec": "ts-node --transpile-only src/index.ts"
}
之后在package.json 文件的 scripts 字段中设置一个运行命令用于启动 nodemon。
"scripts" : {"dev" : "nodemon"}
现在让我们使用该命令来运行应用程序。
最后,让我们添加一些脚本,比如构建和启动。
"scripts":{"dev": "nodemon", "start": "npm run build && node dist/server.js""build": "tsc"
}
如果我们想在生产环境中运行,可以把 NODE_ENV=production 放在命令行中设置成变量 。如果我们想使用条件语句来执行不同的环境,则需要安装 cross-env:
npm i -D cross-env
"scripts":{"dev": "nodemon", "start": "npm run build && cross-env NODE_ENV=production node dist/server.js""build": "tsc"
}
现在我们已经完成了项目的基本配置。
typescript 配置
现在,我们将使用一些额外的工具来改进我们的开发工作流。
typescript有很多的配置,但是我们不能在这一篇文章中涵盖所有的配置,如果我们想学习的话,可以检查官方的配置文档说明。
首先,我们配置了 paths,并用下面的配置更改了 typescript.json 文件。
{"compilerOptions": {"target": "es2020","lib": ["es2020"],"typeRoots": ["node_modules/@types"],"allowSyntheticDefaultImports": true,"experimentalDecorators": true,"emitDecoratorMetadata": true,"forceConsistentCasingInFileNames": true,"moduleResolution": "node","module": "commonjs","pretty": true,"sourceMap": true,"declaration": true,"outDir": "dist","allowJs": true,"noEmit": false,"esModuleInterop": true,"resolveJsonModule": true,"importHelpers": true,"baseUrl": "src","paths": {"@/*": ["*"],"@config/*": ["config/*"],"@controllers/*": ["controllers/*"],"@databases/*": ["databases/*"],"@dtos/*": ["dtos/*"],"@exceptions/*": ["exceptions/*"],"@interfaces/*": ["interfaces/*"],"@middlewares/*": ["middlewares/*"],"@models/*": ["models/*"],"@routers/*": ["routers/*"],"@services/*": ["services/*"],"@utils/*": ["utils/*"]}},"include": ["src//*.ts", "src//*.json", ".env"],"exclude": ["node_modules", "src/http", "src/logs", "src/tests"]
}
正如我们在上面的代码片段中看到的,我们已经添加了许多不存在的路径,我们很快就建立了我们项目的结构。paths 项允许我们定义一系列条目,这些条目重新映射导入到相对于 baseURL 的查找位置。
路径别名:使用者定义的名称来替代较长的路径。
npm i -D tsconfig-paths tslib
tsconfig-paths 用于加载在 tsconfig.json 或者 jsconfig.json 文件中定义的 paths 模块。支持在运行时加载和通过API加载。
tslib 用作包含所有tsconfig助手功能的tsconfig的运行库。
为了使用它们,我们必须修改 nodemon.json 文件:
{"watch" : ["src", ".env" ], "ext":"js,ts,json", "ignore": ["src/logs/*", "src/**/*.{spec,test}.ts"], "exec": "ts-node -r tsconfig-paths/register --transpile-only src/server.ts"}
tsconfig-paths/register 将读取来自 tsconfig.json 中配置的 paths。
验证环境变量
接下来,我们将添加环境变量验证,因为忘记添加环境或不添加环境变量值的正确类型会导致意外错误,导致我们的应用程序故障。
我们使用 envalid 这个库来验证环境变量。
npm i envalid
我们在 src 文件夹下创建一个 utils 文件夹,并创建一个 validateEnv.ts 文件
让我们来写这个配置
import { cleanEnv, port, str } form "envalid";const validateEnv = () =>{cleanEnv(process.env, {NODE_ENV: str(), PORT: port(),})
}export default validateEnv;
写完配置后在 index.ts 文件中引用:
import * as dotenv from 'dotenv'
import express from 'express'
import cors from 'cors'
import helmet from 'helmet'
import validateEnv from '@utils/validateEnv'dotenv.config()validateEnv();
const app = express(); app.use(helmet());
app.use(cors());
app.use(express.json())module.exports = app
我们可以将环境变量更改为无效,例如将端口更改为字符串 PORT= XYZ
执行命令 npm run dev
它将显示一个错误,例如:
Invalid enviroment variables:PORT: Invalid port input: : "xyz"
但是当我们运行 build/start 命令时,我们得到了一个不同的错误:
Error: Cannot find module '@/utils/validateEnv'
This is because we are using a path alias with '@/utils'.
这个是在打包后的 dist 目录里我们的 index.js 文件是 import validateEnv from ‘@/utils/validateEnv’.
当然,我们可以在没有别名的情况下 import。然而,当我们的项目变得更大时,一个路径别名就会变得非常有用。
为了确保 node 找到模块,我们可以使用 ts-alias ,它用 typescript 编译后的相对路径替换别名路径。
npm i -D tsc-alias
我们可以通过将 build 命令修改为以下方式来利用这个包:
"build": "tsc && tsc-alias",
现在让我们运行我们 start 命令来测试它。
此时不应该有任何错误,我们应该在控制台中看到以下内容:
Listening on port 3000