0

Midway 一体化 2.0 版本 正式发布

 2 years ago
source link: https://my.oschina.net/u/4662964/blog/5200583
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

4ea98406-128a-4561-907e-d8f0d7d12d1b.gif

Midway 是一个面向未来的云端一体 Node.js 框架。

开源仓库地址:https://github.com/midwayjs/midway,欢迎关注。

在经过近 6 个月的孵化与研发,Midway 一体化 正式发布 2.0 版本,本次更新速览:

 运行时升级

在 1.0 版本中,我们通过编译器来实现 Hooks 的功能。但这也带来了启动速度慢、语法限制、TS 版本兼容等一系列的问题。

而在 2.0 版本中,我们移除了原有的编译器实现,通过 Node.js AsyncLocalStorage 来实现对 Hooks 功能的支持。而新版本运行时的实现,不仅移除了之前的诸多问题,同时也解锁了更多的可能性。

  • 减少语法限制

在 1.0 中,为了能让编译器正确识别 Hooks,我们要求对 Hooks 的命名、调用、定义均作出了限制。对于开发者而言,命名与使用时都存在一定的负担。

79714d40-55e5-4784-b00a-40e3bf5ff6b1.png

而在 2.0 中,得益于运行时的升级,原有的规则与限制均不复存在。你可以在任何函数中使用 Hooks,不受命名的限制。

如下面的代码,实际上是可以运行的。

5aa441ac-d12f-4262-81c2-d4bf6baaa864.png

当然,我们依然推荐在调用 Hooks 的函数使用 use 命名,便于开发者识别到这是一个 Hooks 调用。

在 1.0 中,由于编译器的限制,Hooks 代码仅能在项目中编写及使用,并不支持发布为 npm 包供其它项目复用。在一定程度上造成了不必要的冗余。

而在 2.0 中,我们支持了 Hooks 代码复用。你可以像开发任何 npm 包一样,去开发可复用的 Hooks,无需额外的处理,项目中使用时正常导入即可。

如下图所示,使用第三方的 Hooks 包,加速开发。(图中的包为示例代码,实际并不存在)

6038d6d8-84fe-435c-a0c7-68dba4f6e64b.png

在 1.0 版中,服务启动时存在大量的编译工作,因此新项目首次启动时间 > 10 秒,并随着后端文件的增加,编译时间也会变长,从而导致了项目越大,开发速度越慢的问题。

db681dca-2195-480f-9125-1755a410934a.png

1.0 启动流程 而在 2.0 版本中,得益于纯运行时方案,新项目启动与重启时间 < 2 秒,且文件数量的增长并不会影响启动时间。在大型项目中将有效减少等待时间。 同时,由于不再需要编译器,2.0 版本在运行时也不会产生 .faas_debug_tmp 此类的缓存文件夹,项目目录更加整洁。

 单元测试

单元测试是 Midway Hooks 在函数式支持上的一块重要拼图。我们希望你能轻松愉悦的完成应用的测试,就像测试纯函数那么简单。 在新版本中,我们支持 runFunction 与 request 两种测试方式,帮助你快速完成接口的测试。
export async function get () {  return { type: 'GET' } }export async function post (message: string) {  return { type: 'POST', message }}

使用 runFunction 测试

import { createApp } from '@midwayjs/hooks-testing-library';import { get, post } from './api'it('GET', async () => {  const app = await createApp();  expect(    await app.runFunction(get);  ).toEqual({ type: 'GET' });  expect(    await app.runFunction(post, '2.0');  ).toEqual({ type: 'POST', message: '2.0' });  });

使用 request 执行完整的 HTTP 测试

import { createApp } from '@midwayjs/hooks-testing-library';import { get, post } from './api'it('GET', async () => {  const app = await createApp();  const response = await app.request(get)  expect(response.status).toEqual(200)  expect(response.type).toEqual('application/json')  const postResponse = await app.request(post, '2.0')  expect(postResponse.status).toEqual(200)  expect(postResponse.type).toEqual('application/json')});

对比与传统 Web 应用的测试,你无需关心单元测试的路径、入参、类型提示等。就像测试纯函数一样测试接口。

传统 Web 应用的测试

a3995366-e162-45af-b01c-e37cc154401c.png

 插件化与函数式配置

在 1.0 中,我们通过 faas-cli 的插件来为项目启用一体化功能。Midway Hooks 与项目是高度定制化且绑定的。 而在 2.0 中,我们将 Midway Hooks 变为了 Midway 的 Component,你可以在任何 Midway 新版本中,启用 Hooks 功能,而不受项目类型,部署模式的限制。 这也意味着,你不仅可以在一体化项目中使用 Hooks,也可以在纯接口开发或 Midway Web 应用开发时使用 Midway Hooks。 新版本的启用方式
import { hooks, createConfiguration } from '@midwayjs/hooks';export default createConfiguration({  imports: [hooks()]});

同时我们也支持了 createConfiguration,支持以函数的方式创建 Midway Configuration,减少 Class 与函数式混用所带来的迷惑感。

 Hook 中间件

在 1.0 版本中,我们对单函数中间件做了支持,但中间件依然遵照 Koa 中间件的语法,也无法在内部使用 Hooks,会给使用者带来困扰。

而在 2.0 版本中,我们新增了 Hooks 中间件的支持,同时也支持了全局中间件与文件级中间件。

原有 1.0 版本的单函数中间件依然保持兼容,你可以手动重构从而使用新的语法。

中间件仅有 next 一个参数,ctx 需要通过 useContext 获得。你也可以在中间件中使用任意的 Hooks。

Logger 中间件

import { Context } from '@midwayjs/faas';import { useContext } from '@midwayjs/hooks';const logger = async (next: any) => {  const ctx = useContext<Context>();  console.log(`<-- [${ctx.method}] ${ctx.url}`);  const start = Date.now();  await next();  const cost = Date.now() - start;  console.log(`[${ctx.method}] ${ctx.url} ${cost}ms`);};
在 2.0 版本中,Midway Hooks 支持三种形式的中间件,用来覆盖不同的使用诉求。
  1. 2.0 全局,对所有 Api 调用都生效
  2. 2.0 文件,对文件内部所有 Api 生效
  3. 1.0 函数,仅对该 Api 函数生效
  • 全局中间件

全局中间件在 configuration.ts 中定义,可以传入任何框架支持的中间件

import { hooks, createConfiguration } from '@midwayjs/hooks';import logger from './logger';// Global Middlewareexport default createConfiguration({  imports: [    hooks({      middleware: [logger],    }),  ],});
  • 文件级中间件

文件级中间件在 Api 文件中定义,通过导出 config.middleware,使得其对该文件内所有 Api 函数生效。

import { ApiConfig } from '@midwayjs/hooks';import logger from './logger';// File Level Middlewareexport const config: ApiConfig = {  middleware: [logger],};export default async (message: string) => {  return { type: 'POST', message }};

 新配置文件项目配置

在 2.0 版本中,我们开放了 Hooks 项目的配置,帮助用户来更好的开发代码。
  • 新配置文件

在 1.0 版本中,我们将部分项目的配置存放于 f.yml 中。由于 f.yml 仅适用于 FaaS,且纯文本无法满足用户自定义的诉求。因此,我们在 2.0 版本中推出了新的配置文件:midway.config.ts。 你可以通过 @midwayjs/hooks 提供的 defineConfig 来配置项目。 基础配置速览
import { defineConfig } from '@midwayjs/hooks';export default defineConfig({  source: 'src/apis',  routes: [    {      baseDir: 'lambda',      basePath: '/api',    },  ],});
支持的所有配置
export interface UserConfig {  /**   * @default false   * Enable superjson to serialize Set/Map/Error/BigInt, default is false   */  superjson?: boolean  // 后端文件夹  source?: string  // 前端路由  routes: ServerRoute[]  // devServer 配置  dev?: {    ignorePattern?: (req: { url: string; [key: string]: any }) => boolean  }}
  • 文件路由配置

在 1.0 中,文件路由在 f.yml 配置。而在 2.0 版本中,文件路由统一在 midway.config.ts 中配置。 在 2.0 中,我们了开放 Hooks 目录的配置,从而适配不同类型的项目。
  1. 默认配置:/src/apis
  2. 自定义:/src/server
  3. 纯接口项目:/src
同时我们也大幅度简化了配置的层级,默认支持 HTTP 路由的配置,从而降低开发者的阅读成本。
  • DevServer 配置

在 2.0 中,我们也支持了 devServer 的配置。 你可以通过传入 dev.ignorePattern 来决定哪些请求应该被 FaaS 函数托管,适用于需要匹配类似 /download/a.css 这种处理文件的情况。

在 2.0 版本中,我们带来了更多场景的支持。

 纯接口场景

在 2.0 中,得益于 Hooks 与 Midway 体系的打通,我们支持了非一体化项目的开发。

纯接口项目的目录结构

b8b935e4-680f-4faf-861b-5a176f0c6c55.png

你可以使用 Hooks 来快速创建接口,并在任何地方调用。而在前后端分离的场景下,我们也在考虑如何为 Hooks 纯接口项目生成前端 SDK 供其它项目使用。

 Web 场景

在 2.0 版本中,我们新增了 Web 服务器部署的支持,这也意味着除了使用 FaaS 平台外,你也可以部署到自己购买的服务器了。 在 Web 场景下,我们默认使用 Koa 作为底层服务框架,这也意味着你可以使用任何 Koa 中间件来开发应用。 例子:使用 koa-bodyparser 来解析 body

import { hooks, createConfiguration } from '@midwayjs/hooks';import bodyParser from 'koa-bodyparser';export default createConfiguration({  imports: [    hooks({      // Global Middleware      middleware: [bodyParser()],    }),  ],});
而在使用上,Web 与 FaaS 的语法是一致的,只是 useContext 传递的上下文变成了 Koa 的 Context。 你可以自定义 useKoaContext 来确保拿到正确的上下文定义

import { useContext } from '@midwayjs/hooks';import { Context } from '@midwayjs/koa';function useKoaContext() {  return useContext<Context>();}export default async () => {  return {    message: 'Hello World',    method: useKoaContext().method,  };};

在 2.0 版本中,我们完全基于开源方式去开发。

同时,我们也在开源社区做了一些大胆的尝试,带来了以下新功能(目前只面向开源社区开放)。

 Vite

在 2.0 中,我们选择 Vite 作为默认支持的前端构建器。

如图所示,作为一个跨前端框架 + 启动速度极快 + 拥抱未来的前端构建器,它与 Midway Hooks 的理念是相匹配的,能为用户提供更好更快的开发体验。

Midway Hooks + Vite

34336401-079d-4035-84e4-5d4173f613b0.png

 Prisma

对于 Midway Hooks 而言,未来很重要的一个方向是建设类型安全的解决方案,而 Prisma 能帮助我们实现这个目标。 Prisma 是新一代的数据库 ORM,通过 Schema 来生成对应的客户端代码,从而帮助你专注于业务逻辑中。

3435c987-af45-4b3a-bb69-08354f731ec2.png

由于数据库客户端是通过 Schema 生成的,因此在生成时就带有类型信息,是可以实现从前后端再到数据库的类型安全解决方案的。

09b3b545-f2a4-4b5c-96a0-26df468f9684.png

开源仓库地址:https://github.com/midwayjs/midway

✿  拓展阅读

作者| 繁易 编辑| 橙子君 出品|阿里巴巴新零售淘系技术 9218c186-5f6f-4058-a218-1788c2a9b98a.jpgfd35d9de-6f29-4374-af9f-6a44bcff271f.png

本文分享自微信公众号 - 淘系技术(AlibabaMTT)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK