使用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