monorepo中使用project refrences,基于fastify的NodeJS Web服务

125 阅读12分钟

视频链接:www.bilibili.com/video/BV1ku…

来咯来咯~新一期视频【使用local pkg的基于fastify的简单web服务:判断以太坊地址是否为具有某个函数的合约地址】更新啦!这期视频里我们在monorepo项目中应用了typescript的project refrences 和 tsc --build来跨pkg对ts代码进行编译 仓库地址:github.com/dmokel/star… 其他链接: 1、关于pnpm的peer dependencies:pnpm.io/npmrc#peer-… 2、关于tsc --build:www.typescriptlang.org/docs/handbo… 3、etherscan浏览器:etherscan.io/ 4、以太坊官网:ethereum.org/en/ 5、Alchemy官网:www.alchemy.com/ 6、stackoverflow问题:stackoverflow.com/questions/7…

嗨,大家好,我是Mokel,主业写代码

喜欢做些视频记录与分享

偶尔折腾小硬件

也拍拍测测数码科技产品

在前两期视频我们了解了monorepo项目的简要基础

并且进行了较为系统完整的nodejs/ts项目的工程化配置

感兴趣的朋友可以订阅这个系列合集

那这期视频我们将在该项目内创建一个local package

同时创建一个使用该local package的

基于fastify的简单web服务

记得点赞投币收藏

为视频的更新注入强劲动力

我们走着!

我们要实现的简单web服务是

对前端传递过来的以太坊地址进行判别

判断该地址是否为具有某个函数的合约地址

比如可以用来判断以太坊地址是否是一个多签钱包合约地址

所以我们将创建一个local package

将判别逻辑封装在其中

并对外暴露一个或多个判别函数

然后我们再创建一个app

该app将主要依赖我们的local package 和 fastify

来创建web服务

提供API接口

接受以太坊地址作为入参

并将判别结果作为响应返回

打开我们在上期视频中完成的项目

我们先来创建一个local package

命名为address-discrimination

然后创建子文件夹和添加基本的文件

并向其中填入相关内容

包括package.json、tsconfig.json 和 index.ts

具体如我所演示

我们来给package.json添加基础内容

我们来具体看看index.ts中的内容

它的函数代码应该长这样

下一步就是要来实现具体的判断逻辑

我们打开浏览器搜索一下

比如搜索"如何判断一个方法是否存在于solidity合约中?"

看一下stack overflow的这个话题

我之前在这个问题下写过一个答案

其中包括函数实现和使用示例

我现在直接复制下来使用

我们需要先安装一下依赖,此时

我们要在具体的package的根目录下安装依赖

而不是如前几期视频中在项目的根目录下安装依赖

这个时候我们有两种方式

一种是进入到对应的目录下

比如在这里

我们可以通过命令行进入到address-discrimination目录下

然后通过pnpm命令安装所需要的依赖

如我所演示

可以看到

我们正确完成了该依赖的安装

回到项目根目录

我们来使用另一种方式安装具体app或pkg所需要的依赖

在项目根目录的package.json中新增一个脚本,如我所演示

然后我们就可以在项目根目录下通过该脚本

从而在address-discrimination package中进行相关操作

比如安装我们还未安装的viem包

如我所演示

可以看到

我们同样也正确完成了依赖安装

你可能会遇到pnpm抛出 missing peer 警告信息

此时你可以在项目根目录下创建 .npmrc 文件

并向其中填入相关配置

如我所演示

关于此内容的详细信息你可以查阅pnpm的官方文档了解更多

代码中还有一些警告

hover上去可以看到是eslint发出的警告

具体的规则是代码中不能出现显式的any类型

我们调整一下这个规则

在 .eslintrc 文件的rules中新增一条规则关闭该警告

如我所演示

可以看到此处已不再报错

这个报错是因为

我们定义了 ret 这个变量

但是没有使用它

所以我们可以直接删除这个变量

另外

代码中还有ts反馈的关于viem包的类型警告

这个可能是viem包的一个类型bug

不过我们在项目根目录的 tsconfig.json 中

已经启用了skipLibCheck选项

所以在使用tsc --build时不会因为这个类型问题而导致编译失败;

而这里你可以通过as any的方式来让编辑器不发出这个类型警告

如我所演示

准备好address-discrimination pkg后

我们来创建address-check application

我们将在该app中

基于fastify和address-discrimination pkg创建web服务

并对外提供API接口

依旧是创建一些基础的文件夹和文件

如我所演示

我们来填充一下package.json

然后填充一下tsconfig.json

然后安装 fastify 和 address-discrimination 依赖

同样的我们先在项目根目录的package.json中新增一个脚本

如我所演示

然后我们通过pnpm命令完成这两个依赖的安装

可以看到我们正确完成了依赖的安装

然后开始编写我们的web服务

首先在src下创建app.ts和api文件夹

在api文件夹内创建endpoints子文件夹

以及routes.ts、server.ts 和 index.ts文件

在endpoints文件夹内创建address-check文件夹

然后在address-check文件夹内

创建single-address子文件夹和index.ts文件

最后在single-address文件夹内创建v1.ts文件

我们先在routes.ts文件中编写代码

如我所演示

然后在server.ts文件中编写代码,如我所演示

然后在index.ts文件中编写代码,如我所演示

然后在app.ts文件中编写代码,如我所演示

现在,我们写好了一个根路径API

它响应一段字符串

其中带有最新的时间信息

我们来启动它

我们先直接通过ts-node来启动该web服务

在终端中执行ts-node命令启动服务

如果你的全局环境没有安装ts-node

那么先将该脚本添加到

address-check application的package.json中

然后在该app的根目录通过pnpm执行它启动服务

你也可以在项目根目录执行它启动服务

可以看到服务均正常启动了

我们新开一个终端

用curl命令调用一下该服务的根路径API

输出了预期的响应

非常好

我们现在已经准备好了一个最简web服务demo

接下来开始添加地址判断的逻辑代码

在我们之前创建的v1.ts文件内编写代码

如我所演示

然后在address-check文件夹下的

index.ts文件中编写代码,如我所演示

回到routes.ts文件内添加一个新的api route

如我所演示

我们来测试一下,先启动web服务

然后用curl命令调用一下api接口

记得传入对应的query参数

可以看到

地址正确的打印在了终端中

接下来

我们来实现地址判别的具体业务逻辑

在src文件夹下创建一个新的子文件夹address-check

并在其中新建index.ts文件

在文件内编写我们的业务逻辑代码

它的核心是一个类

并且该类以私有静态成员变量的方式

存储了我们需要预先初始化好的变量

以公共静态函数的方式对外提供业务逻辑函数

如我所演示

我们需要先安装一下viem包

因为我们会用上这个依赖

然后在index.ts文件内编写代码

这里我使用了一个演示用的Alchemy节点

我们完成了AddressCheckManager这个类的编写

它拥有一个方法

这个方法接收一个以太访地址作为参数

然后可以判断

该以太访地址是否是一个具有

该方法的合约地址

这里的ABI数组,alchemy节点

address-discrimination包的三个isMethodExist函数

以及web3和viem这两个pkg

它们都与区块链开发相关

如果你对此不了解的话,忽略它

直接复制粘贴使用

我将在其他技术分享主题的系列视频里面

和大家交流区块链应用层开发的基础

比如Nft,比如zk-rollup等等

完成了业务逻辑类的编码后

回到routes.ts文件内

跳转到我们的checkSingleAddressV1函数

更新该函数的代码

在其中import并使用我们刚刚编码好的业务逻辑函数

并将结果作为响应返回

更新好代码后,我们来测试一下

启动web服务

然后在终端中执行curl命令

可以看到

预期的响应打印在了终端中

到目前为止

我想你可能已经萌生了一些疑惑

首先是我们这繁多的文件夹和文件

毕竟我们仅仅只写了一个非常简单的web api

就创建了这么多文件夹和文件

其实这是有意为之

主要是为了演示假如在功能和代码量较大的情况下

可以采取的其中一种代码组织的方式

比如说,假如我们还有graphql服务

那么我们可以在api文件夹下

新建一个graphql文件夹来组织相关的代码

此外,如果我们的项目功能模块比较多

需要拆分为几个不同的领域

那么我们就可以在src文件夹下

新建其他的领域文件夹来组织相关的代码

现在

我们的ts代码已经可以通过ts-node来运行了

但这并不是一个生产环境下合适的启动服务的方式

我们还需要依赖tsc来对ts代码进行编译

构建js产物

从而能够在生产环境中使用nodejs运行时直接运行js启动服务

除了使用tsc对ts代码进行编译外

我们还可以使用esbuild,rollup

webpack等编译工具来对ts代码进行编译压缩

接下来

我们先在address-check app的package.json中新增几个脚本

如我所演示

关于tsc --build你可以查阅文档了解更多详细信息

同时

我们也要来更新一下tsconfig.json文件

tsc命令将加载当前项目根目录下的tsconfig.json文件

作为配置文件

在tsconfig.json文件中新增这几部分内容

然后在终端中执行pnpm命令

如我所演示

注意是在monorepo项目根目录下执行

可以看到address-check 应用内

生成了dist文件夹和tsbuildinfo文件

其中dist文件夹内是tsc工具

从src下的ts代码编译出来的js代码和d.ts文件

然后我们来执行一下编译后的js代码

通过pnpm命令执行

如我所演示

很不幸运,报错了

而且可以看到错误是来自于

我们的本地包 address-discrimination

这里我们对以下几个方面进行更新

首先是 address-discrimination 包的 package.json 文件

我们更新main配置项

如我所演示

然后是 address-discrimination 包的 tsconfig.json 文件内

新增以下几项内容

最后是回到address-check app中

在 tsconfig.json 文件中新增 refrences 选项

我们提到的project reference就是应用在这里

这几项更新的整体作用是

通过project refrences向tsc指明

address-check应用依赖于address-discrimination包

从而在我们通过tsc --build编译address-check应用的ts源码时

tsc能够自动对address-discrimination包进行必要的源码编译

而对address-discrimination包的

tsconfig.json文件的修改

是控制tsc编译address-discrimination时的配置项

同时package.json的main入口变更为dist文件夹下的js产物

因为我们后面启动address-check应用是直接运行它的js产物

故而被import的address-discrimination包

也要将其入口更新为js产物

此时我们会发现address-check应用下的

address-check logic有报错

报错信息为

Cannot find module '@.../address-discrimination'

or its corresponding type declarations

这是因为我们刚刚修改了address-discrimination包的入口点

即package.json文件的main字段

我们现在可以不管它

我们先删掉之前构建的dist文件夹

和tsconfig.tsbuildinfo文件

然后在终端中执行pnpm命令

如我所演示

可以看到,不仅address-check app下

有了tsc工具构建的dist文件夹下的js产物

而且address-discrimination pkg下

也有了tsc工具构建的dist文件夹下的js产物

而这正是ts的project refrences 和 tsc --build的作用

ts的project refrences能够基于我们在tsconfig.json文件中

定义的references来检测被依赖的本地包是否有进行正确的编译

或者是否是最新的编译,如果没有

将会自动对被依赖的包执行tsc --build进行编译更新

我们reload一下vscode窗口,此时

address-check应用下的address-check logic不再有报错

且address-discrimination包也能够正确的跳转

我们再来启动服务试试

看看是否能够正常运行

可以看到,服务正常启动

我们通过curl命令请求接口试试

接口返回了正确的响应

都非常符合我们的预期

视频最后

我们可以再对相关配置项做一些调整

比如我们可以把address check应用的

tsconfig.json文件的这三个选项禁用

如此一来

address check应用在编译时不进行增量编译

同时不生成d.ts文件

从而clean脚本

也不需要删除tsbuildinfo文件了

我们更新一下 .gitignore 文件

然后提交一个commit

至此

我们便完成了本期视频的所有内容

其中逐步探究了一些基础性的内容

这些内容能够让我们对monorepo项目的作用

有更进一步的认识

同时也让我们对ts及其project references

有了还算比较充分的了解

下期视频

我们将来探索一下nodejs/ts项目的github发版与npm发包

下期视频的内容会让我们对ts的编译

包的export和import有更进一步的认识

我们下期视频,不见不散~