TypeScript在react项目中的实践 (3)

关于ESLint的配置文件.eslintrc,在本项目中存在两份。一个是根目录的blued-typescript,另一个是client-src下的blued-react + blued-typescript。
因为根目录的更多用于node项目,所以没必要把react什么的依赖也装进来。

# .eslintrc extends: blued-typescript # client-src/.eslintrc extends: - blued-react - blued-typescript

一个需要注意的小细节
因为我们的react与typescript实现版本中都用到了parser。
react使用的是babel-eslint,typescript使用的是typescript-eslint-parser。
但是parser只能有一个,从option的命名中就可以看出extends、plugins、rules,到了parser就没有复数了。
所以这两个插件在extends中的顺序就变得很关键,babel现在并不能理解TS的语法,但好像babel开发者有支持TS的意愿。
但就目前来说,一定要保证react在前,typescript在后,这样parser才会使用typescript-eslint-parser来进行覆盖。

node层的修改

除了上边提到的两端公用代码以外,还需要添加一个controller用于吐页面,因为使用的是routing-controllers这个库,渲染一个静态页面被封装的非常棒,仅仅需要修改两个页面,一个用于设置render模版的根目录,另一个用来设置要吐出来的模版名称:

// controller/index.ts import { Get, Controller, Render, } from 'routing-controllers' @Controller('http://www.likecs.com/') export default class { @Get('http://www.likecs.com/') @Render('index') // 指定一个模版的名字 async router() { // 渲染页面时的一些变量 // 类似之前的 ctx.state = XXX return { title: 'First TypeScript React App', } } } // app.ts import koaViews from 'koa-views' // 添加模版所在的目录 // 以及使用的渲染引擎、文件后缀 app.use(koaViews(path.join(__dirname, '../views'), { options: { ext: 'ejs', }, extension: 'ejs', }))

如果是多个页面,那就创建多个用来Render的ts文件就好了

深坑,注意

目前的routing-controller对于Koa的支持还不是很好,(原作者对Koa并不是很了解,导致Render对应的接口被请求一次以后,后续所有的其他的接口都会直接返回该模版文件,原因是在负责模版渲染的URL触发时,本应返回数据,但是目前的处理却是添加了一个中间件到Koa中,所以任何请求都会将该模版文件作为数据来返回)所以@Render并不能适用于Koa驱动。
不过我已经提交了PR了,跑通了测试用例,坐等被合并代码,但是这是一个临时的修改方案,涉及到这个库针对外部中间件注册的顺序问题,所以对于app.ts还要有额外的修改才能够实现。

// app.ts 的修改 import 'reflect-metadata' import Koa from 'koa' import koaViews from 'koa-views' import { useKoaServer } from 'routing-controllers' import { distPath } from './config' // 手动创建koa实例,然后添加`render`的中间件,确保`ctx.render`方法会在请求的头部就被添加进去 const koa = new Koa() koa.use(koaViews(path.join(__dirname, '../views'), { options: { ext: 'ejs', }, extension: 'ejs', })) // 使用`useKoaServer`而不是`createKoaServer` const app = useKoaServer(koa, { controllers: [`${__dirname}/controllers/**/*{.js,.ts}`], }) // 后续的逻辑就都一样了 export default app

当然,这个是新版发出以后的逻辑了,基于现有的结构也可以绕过去,但是就不能使用@Render装饰器了,抛开koa-views直接使用内部的consolidate:

// controller/index.ts // 这个修改不需要改动`app.ts`,可以直接使用`createKoaServer` import { Get, Controller, } from 'routing-controllers' import cons from 'consolidate' import path from 'path' @Controller() export default class { @Get('http://www.likecs.com/') async router() { // 直接在接口返回时获取模版渲染后的数据 return cons.ejs(path.resolve(__dirname, '../../views/index.ejs'), { title: 'Example For TypeScript React App', }) } }

目前的示例代码采用的上边的方案

小结

至此,一个完整的TS前后端项目架构就已经搭建完成了(剩下的任务就是往骨架里边填代码了)。
我已经更新了之前的typescript-exmaple 在里边添加了本次重构所使用的一些前端TS+React的示例,还包括针对@Render的一些兼容。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgjjss.html