前言
很多时候,我们在学习了某个新东西以后,却不知道如何在项目中运用自己学到的新东西。本篇旨在使用 Node.js + TypeScript + Express 实现一个简单的后台服务器,以此更加深入的理解 ts 在实际开发中的运用。
基础知识
阅读本篇专栏前,你需要掌握以下知识:
- 掌握 JavaScript 基础;
- 了解 Node.js 及 Express 框架;
- 了解 TypeScript 基本知识,可参考 TypeScript 要点知识整理。
项目初始化
- 创建项目文件夹 simple-login-node,进入文件夹;
- 进入项目文件夹,通过 npm init ,tsc --init 以及 tslint --init 初始化项目,初始化前,请确保已全局安装过 npm、typescript 以及 tslint,可通过以下命令进行安装;
npm install -g npm
npm install -g typescript
npm install -g tslint
复制代码
- 在根目录下创建 /src 目录,在目录下建立 app.ts 文件。
进行以上操作后,我们的目录结构如下:
具体文件说明/src/app.ts // 程序入口文件
.npmrc // 项目 npm 配置文件,可针对项目单独设置 npm 的配置
package.json // 项目模块描述文件
tsconfig.json // typescript 配置文件
tslint.json // tslint 配置文件
复制代码
以上就是一个使用 typescript 编写的 node.js 项目的基本结构,我们来进一步细分,每个配置有哪些重要的配置呢?
package.json
- scripts
配置指令集合,当我们使用 npm run * 的时候,* 表示我们在 script 节点下配置的指令。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
复制代码
以上配置,当我们执行 npm run test的时候,实践会将 test 后配置的语句进行执行,即 echo "Error: no test specified" && exit 1
- dependencies
在项目下使用 npm install --save * 安装的包,及其版本 - devDependencies
在项目下使用 npm install --save-dev * 安装的包,仅在开发模式下安装。因为 typescript 仅在编译时检查代码,即仅在开发时有效,因此很多 typecript 相关模块以及带声明文件的第三方模块仅在开发模式下安装。
下面我们安装 express 模块,在项目根目录下运行:
npm install --save express // 安装普通 express 模块,并在 dependencies 下生成包记录
npm install --save-dev @types/express // 安装带有声明文件的 express 模块,并在 devDependencies 下生成包记录,仅开发模式下安装。
复制代码
此时 package.json 如下(仅贴关键代码):
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"@types/express": "^4.17.0"
}
复制代码
tsconfig.json
如果一个目录下存在存在 tsconfig.json 文件,那么就意味着这个目录是 typescipt 项目的根目录。tsconfig.json 定义了用来编译这个项目的根目录及编译选项。让我们一起来看看其中的一些关键配置项。
{
/* 编译选项 */
"compilerOptions": {
"target": "es6", // 指定 EECMAScript 的目标版本, 这里我们采用 es6
"module": "commonjs", // 指定编译生成哪个模块的系统代码,考虑到兼容性,这里我们设置成 commonjs
"outDir": "dist", // 编译输出目录,即 .ts 文件编译成 .js 文件后的输出目录。这里设置为根目录下的 /dist 目录
"strict": true, // 严格模式
"noImplicitAny": false, // 在表达式和声明上有隐含的 any类型时报错。设为 false 避免当类型推论为 any 时报错
"moduleResolution": "node", // 决定如何处理模块。设置为 node
"baseUrl": "./", // 定义 ts 项目的根目录,设置 paths 前必须设置
//定义路径别名,即当我们通过路径引入一个模块时,可以使用别名来进行引入,这里第一个 * 设置是为了引入第三方模块; 第二个 '@/*' 则是为了直接快捷的导入 /src 下的模块。
"paths": {
"*": ["node_modules/*", "src/types/*"],
"@/*": ["src/*"]
}
"esModuleInterop": true // 模块导入方式
},
"include": ["src"], // 需要编译的 ts 文件,这里设置为 src 目录下的所有文件
"exclude": ["node_modules"] // 编译需要排除的文件目录
}
复制代码
tslint.json
tslint 配置文件,用于检查代码是否符合设置的代码规范,不符合将会提示对应错误,具体设置请看文章最后的源码。
搭建 express 服务
- 安装 body-parser 模块,用于处理 post 请求的请求体
npm install --save body-parser
复制代码
- 在 /src 目录下建立 config 目录下,目录下建立 index.ts,用于存放项目的一些开修改配置,我们将 Express 服务占用的端口写在其中,代码如下:
const systemConfig = {
port: 8000,
};
export default {
systemConfig,
};
复制代码
- 我们这可是 typescript 项目,我们试着定义一下 配置中 systemConfig 变量的类型,在 /src 目录下建立 types 目录,用于存放项目的所有类型定义,在 /types 下建立 config.ts 文件,对类型进行定义,并在配置文件中引入
// /src/types/config.ts
export interface ISystemConfig {
port: number;
}
// /src/config/index.ts
import { ISystemConfig } from "@/types/config";
const systemConfig: ISystemConfig = {
port: 8000,
};
复制代码
这样就限定了 systemConfig 对象下只有一个属性 port,且类型为 number,并且这样我们在使用 systemConfig 时,将会有代码提示其内部属性哦。
4. 在 /src/app.ts 下创建 Express 服务
// 第三方模块
import bodyParser from 'body-parser';
import express from 'express';
import { NextFunction, Request, Response } from 'express'; // express 申明文件定义的类型
// 自定义模块
import { systemConfig } from './config';
const app = express();
// 处理 post 请求的请求体,限制大小最多为 20 兆
app.use(bodyParser.urlencoded({ limit: '20mb', extended: true }));
app.use(bodyParser.json({ limit: '20mb' }));
// error handler
app.use(function(err: Error, req: Request, res: Response, next: NextFunction) {
return res.sendStatus(500);
});
app.listen(systemConfig.port, function() {
console.log(`the server is start at port ${systemConfig.port}`);
});
export default app;
复制代码
项目运行
大功告成,我们来运行试试
node ./src/app.ts
复制代码
但是。。语法错误
这时候我们想起来, ts 文件是无法直接运行,我们来先编译一下自己的 ts 代码,在根目录运行tsc
复制代码
还记得我们之前在 tsconfig.json 中设置了 编译后的 js 代码的输出目录为 /dist 目录,我们执行命令后,可以看到 /dist 目录在根目录下生成了!
来看看 dist 目录下结构 可以看到,所有代码都生成了对应的 js 代码,且目录结构与 ts 代码目录结构一致。 我们运行 app.js 看看 耶!成功了!我们浏览器访问看看 因为没有定义具体的接口,所以返回了 “Cannot Get /”,但是我们服务器已经启动了!一个问题
难道我们更新了代码都要重新编译,然后在启动服务吗?
解决办法
安装 nodemon 以及 ts-node 用于监控 指定目录 ts 代码的改动,改动后自动编译运行项目。
// 仅开发环境安装
npm install --save-dev nodemon // nodemon 用来监视node.js应用程序中的任何更改并自动重启服务
npm install --save-dev ts-node // ts-node 命令可直接执行 TypeScript 源文件而不需要预先编译
复制代码
安装完成后,我们使用 nodemon 监控 /src 下所有 ts 文件的改动,当改动发生后,使用 ts-node 直接重新app.ts。命令如下:
nodemon --watch 'src/' -e ts --exec 'ts-node' ./src/app.ts
复制代码
可以看到,当我们改动 config 中端口号为 8001 后,项目真的有自动重启,棒棒哒!
根据 ten_noc 的提醒,在windows下,脚本命令会提示找不到ts-node,需要安装cross-env,然后将启动命令修改为:
cross-env nodemon --watch 'src/' -e ts --exec 'ts-node' ./src/app.ts
复制代码
优化一下
可以看到,上面那条启动命令有点儿长,每次都输入这么一长串是不是不太友好!那么有没有简化的方式呢?有!还记得前面我们说过,package.json 中可以配置启动脚本!
// 在 script 标签中加入 dev 配置
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon --watch 'src/' -e ts --exec 'ts-node' ./src/app.ts"
}
复制代码
然后我们只要运行 npm run dev 就可以启动项目了,看看效果
耶!给自己一个赞0.0总结及源码
本篇简单地搭建了一个基于 typecript 的 express 服务,关于 typescript,笔者也是在学习过程中,如果有不足的地方欢迎各位大佬在评论区指出。如果你觉得对你有帮助的话,不要忘了点赞和关注哦^o^
本节源码地址:github.com/liyuezu/sim…