内容简介:在大概1年前接触了typescript之后, 日渐被它所吸引. 甚至一个简单的本地测试文件综上, 于是就有了今天这个话题:答案是: 不存在的:sweat_smile:
在大概1年前接触了typescript之后, 日渐被它所吸引. 甚至一个简单的本地测试文件 node ./test.js
有时也会切到 ts-node ./test.ts
. 在同样的时间节点之前, 还是会不时地去学学node, mongodb相关的. 可是, 由于懒(需)惰(求), 在很久没碰之后, 很多知识点都忘了!:sleeping:
综上, 于是就有了今天这个话题:
论 如何在工作时间之余完成自己的个人项目并实现按时上床睡觉
答案是: 不存在的:sweat_smile:
项目简介
项目会不断维护. 无论是client端还是server端, 都只提供简单的模板式的功能.
地址
client ts-react-webpack
server showcase
依赖
typescript是两端的基调
client
- webpack-4.x
- typescript-3.0.x
- react-16.4.x
- mobx-5.x
- ant design
- ...
server
centos上 mongodb 的官网安装教程 , 其他系统请自行查阅.
- nestjs
- dotenv
- jsonwebtoken
- mongodb(mongoose)
- ...
需要讲一下我为什么选了 nestjs :
nestjs
将 typeScript
引入并基于 express
封装. 意味着, 它与绝大部分 express
插件的兼容性都很好.
nestjs
的核心概念是提供一种体系结构, 它帮助开发人员实现层的最大分离, 并在应用程序中增加抽象.
此外, 它对测试是非常友好的...
也需要声明的是, nestjs
的依赖注入特性是受到了 angular
框架的启发, 相信做 angular
开发的对整个程序体系会更容易看懂.
具体实现
server
简单介绍下几个主流程模块
main.ts
我是用nest-cli工具初始化项目的, 一切从 src/main.ts
开始
import { NestFactory } from '@nestjs/core' import * as dotenv from 'dotenv' import { DOTENV_PATH } from 'config' // 优先执行, 避免引用项目模块时获取环境变量失败 dotenv.config({ path: DOTENV_PATH }) import { AppModule } from './app.module' async function bootstrap() { const app = await NestFactory.create(AppModule) // 支持跨域 app.enableCors() await app.listen(9999) } bootstrap() 复制代码
同样地, 我们可以提供一个 express
实例到 NestFactory.create
:
const server = express(); const app = await NestFactory.create(ApplicationModule, server); 复制代码
这样我们就可以完全控制 express
实例生命周期, 比如官方 FAQ中说到的创建几个同时运行的服务器
在我本地开发的时候, 根目录上还有一个 .dev.env
, 这是未提交到github的, 因为里面包含了我个人的 mongodb
远程 ip
地址 其他内容与github上的 .env
一致, 因为我本地并不想再安装一遍 mongodb
, 如果是刚刚把项目拉下来就跑起来的, 无论如何你都需要一个 mongodb
服务, 当然你是可以本地安装就好了.
还需要提及到一点就是调试:
以前在vscode上调试node程序都需要在调试栏新增配置, 然后利用该配置去跑起应用才能实现断点调试, 新版的vscode支持autoAttach功能, 使用 Command
+ Shift
+ P
唤起设置功能面板
启动它!
这样, 在项目的 .vscode/setting.json
里面会多了一个选项: "debug.node.autoAttach": "on"
, 在我们的启动script里面加上 --inspect-brk
就可以实现vscode的断点调试了. 对应地, npm run start:debug
是我的启动项, 可参考 nodemon.debug.json
app.module.ts
import { Module } from '@nestjs/common' import { MongooseModule } from '@nestjs/mongoose' import { DB_CONN } from 'config/db' import { AppController } from './app.controller' import { AppService } from './app.service' import modules from 'routers' @Module({ imports: [ MongooseModule.forRoot(DB_CONN, { useNewUrlParser: true, }), ...modules, ], controllers: [AppController], providers: [AppService], }) export class AppModule {} 复制代码
每个 Nest 应用程序至少有一个模块, 即根模块. 根模块是 Nest 开始安排应用程序树的地方. 事实上, 根模块可能是应用程序中唯一的模块, 特别是当应用程序很小时, 但是对于大型程序来说这是没有意义的. 在大多数情况下, 您将拥有多个模块, 每个模块都有一组紧密相关的功能. 当然, 模块间也可以共享.
概念 | 解释 |
---|---|
providers | 由 Nest 注入器实例化的提供者,并且可以至少在整个模块中共享 |
controllers | 必须创建的一组控制器 |
imports | 导入模块所需的导入模块列表 |
exports | 此模块提供的提供者的子集, 并应在其他模块中使用 |
AppController
在这个程序当中只是为了测试能返回 Hello World!!!
, 其实它不是必须的, 我们可以把它直接干掉, 把全部接口, 全部逻辑放到各个 module
中实现, 以 modules/user
为例, 接着往下看.
modules/user
目录结构
user ├── dto -------------- 数据传输对象 ├── index.ts --------- UserModule, 概念同AppModule ├── controller.ts ---- 传统意义的控制器, `Nest`会将控制器映射到相应的路由 ├── interface.ts ----- 类型声明 ├── schema.ts -------- mongoose schema ├── service.ts ------- 处理逻辑 复制代码
有必要讲讲 controller.ts
和 service.ts
, 这是nestjs的概念中很重要的部分
controller.ts
import { Get, Post, Body, Controller } from '@nestjs/common' import UserService from './service' import CreateDto from './dto/create.dto' @Controller('user') export default class UserController { constructor(private readonly userService: UserService) {} @Get() findAll() { return this.userService.findAll() } @Post('create') create(@Body() req: CreateDto) { return this.userService.create(req) } } 复制代码
装饰器路由为每个路由(user)声明了前缀,所以 Nest
会在这里映射每个 /user
的请求
@Get()
装饰器告诉 Nest
创建此路由路径的端点
同样地, @Post()
也是如此, 并且这类Method装饰器接收一个 path
参数, 如 @Post('create')
, 那么我们就可以实现post到路径 /user/create
到此, 往后的逻辑交给 service
实现
service.ts
import { Injectable } from '@nestjs/common' import { InjectModel } from '@nestjs/mongoose' import { Model } from 'mongoose' import logger from 'utils/logger' import { cryptData } from 'utils/common' import ServiceExt from 'utils/serviceExt' import { IUser } from './interface' import CreateDto from './dto/create.dto' @Injectable() export default class UserService extends ServiceExt { constructor(@InjectModel('User') private readonly userModel: Model<IUser>) { super() } async create(createDto: CreateDto) { if (!createDto || !createDto.account || !createDto.password) { logger.error(createDto) return this.createResData(null, '参数错误!', 1) } const isUserExist = await this.isDocumentExist(this.userModel, { account: createDto.account, }) if (isUserExist) { return this.createResData(null, '用户已存在!', 1) } const createdUser = new this.userModel({ ...createDto, password: cryptData(createDto.password), }) const user = await createdUser.save() return this.createResData(user) } async findUserByAccount(account: string) { const user = await this.userModel.findOne({ account }) return user } async findAll() { const users = await this.userModel.find({}) return this.createResData(users) } } 复制代码
至此, 我们运行 npm run start:dev
启动一下服务:
直接在浏览器端访问 http://localhost:9999/#/
没错, 的确失败了!!! 因为我们使用了 jsonwebtoken
, 在 modules/auth
可以看到它的实现.
现在我们在 postman
中登录了再试试吧!
bingo!!!
(如果是想拉下来跑的话, 也可以照着 schema
的格式用 postman
先伪造条用户数据, 把系统打通!!!)
client
关于client端的实现我不会细讲, 可以看 项目github 我之前的文章( typescript-react-webpack4 起手与踩坑 ), 项目结构会有改动.
讲一下接入了真实服务器之后http请求对于token的一些处理, 查看 http.ts
首先是创建 axios
实例时需要在 header
处把token带上
const axiosConfig: AxiosRequestConfig = { method: v, url, baseURL: baseUrl || DEFAULTCONFIG.baseURL, headers: { Authorization: `Bearer ${getCookie(COOKIE_KEYS.TOKEN)}` } } const instance = axios.create(DEFAULTCONFIG) 复制代码
cookie也可以存放在localStorage
另外一点是, 对应服务端返回的token错误处理
const TOKENERROR = [401, 402, 403] let authTimer: number = null ... if (TOKENERROR.includes(error.response.status)) { message.destroy() message.error('用户认证失败! 请登录重试...') window.clearTimeout(authTimer) authTimer = window.setTimeout(() => { location.replace('/#/login') }, 300) return } 复制代码
总结
两端项目都是简单的模板项目, 不存在什么繁杂的业务, 属于比较初级的学习实践. 对 nestjs
的掌握程度有限, 只是拿来练练手. 可能后续会基于这篇文章继续深入地去讲讲, 比如部署之类的, 两个项目也会不断去维护. 后续也有计划会合二为一. 看时间吧!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- react同构实践——实现自己的同构模板
- 网站模板 | 现代时尚创新创意投资组合HTML5模板设计
- ReportLibrary 报表模板库新增 21 张报表模板,加入报表导出功能!
- ReportLibrary 报表模板库新增 21 张报表模板,加入报表导出功能!
- 工具集核心教程 | 第五篇: 利用Velocity模板引擎生成模板代码
- Word 模板引擎 poi-tl V1.3.0 发布,新增模板语法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。