midway Documentation

A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and...

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy midway on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name midway -p 6379:6379 --restart always redis:7.4.11
Configured Services & Ports
⚙️ redis
image: redis:7.4.11
🔌 Ports: 6379:6379
⚙️ rabbitmq
image: rabbitmq:3-management
🔌 Ports: 5672:5672, 15672:15672
⚙️ zookeeper
image: wurstmeister/zookeeper
🔌 Ports: 2181:2181
⚙️ kafka
image: wurstmeister/kafka
🔌 Ports: 9092:9092
⚙️ etcd
image: gcr.io/etcd-development/etcd:v3.7.2
🔌 Ports: 2379:2379, 2380:2380
⚙️ mongodb
image: mongo:4.4
🔌 Ports: 27017:27017
⚙️ mosquitto
image: eclipse-mosquitto:latest
🔌 Ports: 1883:1883, 8883:8883
⚙️ consul
image: hashicorp/consul:1.22.7
🔌 Ports: 8500:8500, 8600:8600/udp
docker-compose.yml
yaml (docker-compose.yml)
services:
  redis:
    image: redis:7.4.11
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    ports:
      - "6379:6379"

  rabbitmq:
    image: rabbitmq:3-management
    healthcheck:
      test: ["CMD", "rabbitmqctl", "node_health_check"]
      interval: 10s
      timeout: 5s
      retries: 5
    ports:
      - "5672:5672"
      - "15672:15672"

  zookeeper:
    image: wurstmeister/zookeeper
    environment:
      ALLOW_ANONYMOUS_LOGIN: "yes"
    healthcheck:
      test: ["CMD", "sh", "-c", "echo mntr | nc -w 2 -q 2 localhost 2181"]
      interval: 10s
      timeout: 5s
      retries: 5
    ports:
      - "2181:2181"

  kafka:
    image: wurstmeister/kafka
    environment:
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092  # 保留你原本配置
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_PORT: 9092
    healthcheck:
      test: ["CMD", "sh", "-c", "kafka-broker-api-versions.sh --version"]
      interval: 10s
      timeout: 5s
      retries: 5
    ports:
      - "9092:9092"
    depends_on:
      - zookeeper

  etcd:
    image: gcr.io/etcd-development/etcd:v3.7.2
    command:
      - /usr/local/bin/etcd
      - --name
      - s1
      - --data-dir
      - /etcd-data
      - --listen-client-urls
      - http://0.0.0.0:2379
      - --advertise-client-urls
      - http://0.0.0.0:2379
      - --listen-peer-urls
      - http://0.0.0.0:2380
      - --initial-advertise-peer-urls
      - http://0.0.0.0:2380
      - --initial-cluster
      - s1=http://0.0.0.0:2380
      - --initial-cluster-token
      - tkn
      - --initial-cluster-state
      - new
    ports:
      - "2379:2379"
      - "2380:2380"

  mongodb:
    image: mongo:4.4
    ports:
      - "27017:27017"

  mosquitto:
    image: eclipse-mosquitto:latest
    ports:
      - "1883:1883"
      - "8883:8883"
    volumes:
      - ./packages/mqtt/scripts/mosquitto.conf:/mosquitto/config/mosquitto.conf

  consul:
    image: hashicorp/consul:1.22.7
    command: agent -dev -client=0.0.0.0
    ports:
      - "8500:8500"
      - "8600:8600/udp"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8500/v1/status/leader"]
      interval: 10s
      timeout: 5s
      retries: 5

1. Project Overview & Quickstart (midwayjs/midway)

File: README.md

English | 简体中文

资源

特性

  • 🐘 全功能:支持 Web 应用/Serverless/FaaS/微服务/小程序后端等多种场景,基于装饰器和依赖注入开发企业级应用
  • 🐦 前端集成:全新的云端一体应用研发体验,零 API 调用,使用 "React Hooks " 风格一体研发
  • 🐴 跨平台:支持部署至普通 Server 或 Serverless/FaaS 环境
  • 🐶 扩展:组件化扩展能力,另外支持使用 Koa/Express/Egg.js 生态插件
  • 🐂 示例: 官方提供多种场景的示例代码,方便开发者快速上手
  • 🛡 TypeScript 全面支持

描述

Midway 是一个适用于构建 Serverless 服务,传统应用、微服务,小程序后端的 Node.js 框架。

Midway 可以使用 Koa,Express 或 Egg.js 作为基础 Web 框架。它还提供了独立使用的基本解决方案,例如 Socket.io,GRPC,Dubbo.js 和 RabbitMQ 等。

此外,Midway 也适用于前端/全栈开发人员的 Node.js 无服务器框架。构建下一个十年的应用程序。可在 AWS,阿里云,腾讯云和传统 VM /容器上运行。与 React 和 Vue 轻松集成。 🌈

Demo

使用装饰器开发 Web 应用

ts
import { Controller, Get, Provide } from '@midwayjs/decorator';

@Provide()
@Controller('/')
export class HomeController {

  @Get('/')
  async home() {
    return `Welcome to midwayjs!`;
  }
}

使用函数开发全栈应用

后端代码
src/apis/lambda/index.ts

typescript
import {
  Api,
  Get,
  Query,
  useContext,
} from '@midwayjs/hooks';

export default Api(
  Get(),
  Query<{
    page: string;
    limit: string;
  }>(),
  async () => {
    const ctx = useContext();
    return {
      page: ctx.query.page,
      limit: ctx.query.limit,
    };
  }
);

前端调用
src/page/index.tsx

typescript
import getArticles from './api';
const response = await getArticles({
  query: { page: '0', limit: '10' },
});
console.log(response); // { page: '0', limit: '10' }

手动调用

typescript
fetch('/api/articles?page=0&limit=10')
  .then((res) => res.json())
  .then((res) => console.log(res)); // { page: '0', limit: '10' }

快速上手

bash
$ npm -v

## 选择模版
$ npm init midway

## 进入项目路径
cd my_midway_app && npm run dev

文档和社区

社区优秀示例展示

1、Cool-Admin - 一个很酷的后台权限管理框架

VSC Plugin

答疑

群里会有热心的朋友,也会有新版本发布推送。

贡献

请告知我们可以为你做些什么,不过在此之前,请检查一下是否有 已经存在的Bug或者意见。

如果你是一个代码贡献者,请参考代码贡献规范。

谁在使用

你也想加 Logo ?可以点击 这里 添加。

License

我们的代码使用 MIT 协议,请放心使用。


File: benchmark/readme.md

Benchmark

you can run benchmark here for midway framework.

bash
$ ./ready.sh
$ node index

result like this

text
Waiting for Midway 3 with request context to initialize...
Running benchmark on Midway 3 with request context...
Midway 3 with request context QPS:  2374.4
Waiting for Midway 3 with async hooks to initialize...
Running benchmark on Midway 3 with async hooks...
Midway 3 with async hooks QPS:  2495.81

File: packages/ws/README.md

midway framework for WebSocket


this is a sub package for midway.

Document: https://midwayjs.org

License

MIT


File: packages/web-koa/README.md

midway for koa


this is a sub package for midway.

Document: https://midwayjs.org

License

MIT


File: packages/web-express/README.md

midway for express


this is a sub package for midway.

Document: https://midwayjs.org

License

MIT


File: packages/web/README.md

@midwayjs/web


this is a sub package for midway.

Document: https://midwayjs.org

License

MIT


File: packages/view-nunjucks/README.md

midway-view-nunjucks


this is a sub package for midway.

Document: https://midwayjs.org

License

MIT


File: packages/view-ejs/README.md

midway-view-ejs


this is a sub package for midway.

Document: https://midwayjs.org

License

MIT


File: packages/view/README.md

midway-view

Base view component for midway.

Install

@midwayjs/view don't have build-in view engine, So you should choose a template engine like ejs, and install @midwayjs/view-ejs.
View component will be auto install and enable by import view-ejs.

bash
$ npm i @midwayjs/view-ejs --save

Usage

First, import component in src/configuration.ts.

typescript
import { Configuration } from '@midwayjs/core';
import * as view from '@midwayjs/view-ejs';
import { join } from 'path'

@Configuration({
  imports: [
    // ...
    view
  ],
  importConfigs: [
    join(__dirname, 'config')
  ]
})
export class ContainerLifeCycle {
}

Configure the mapping, the file with .ejs extension will be rendered by ejs.

typescript
// src/config/config.default.ts
export const view = {
  defaultViewEngine: 'ejs',
  mapping: {
    '.ejs': 'ejs',
  },
};

// ejs config
export const ejs = {};

In controller, you can call ctx.render.

typescript
import { Inject, Provide } from '@midwayjs/core';
import { Context } from '@midwayjs/koa';

@Controller('/')
export class HomeController {

  @Inject()
  ctx: Context;

  @Get('/')
  async render(){
    await this.ctx.render('hello.ejs', {
      data: 'world',
    });
  }
}

Use multiple view engine

@midwayjs/view support multiple view engine, so you can use more than one template engine in one application.

If you want add another template engine like nunjucks, then you can add @midwayjs/view-nunjucks component.

Configure the plugin and mapping

typescript
// src/config/config.default.ts
export const view = {
  mapping: {
    '.ejs': 'ejs',
    '.nj': 'nunjucks',
  },
};

You can simply render the file with .nj extension.

typescript
await this.ctx.render('user.nj');

Write a view engine

Create a view engine class first, and implement render and renderString, if the template engine don't support, just throw an error.

typescript
// lib/view.ts
import { Provide } from '@midwayjs/core';

@Provide()
export class MyView {

  @Config('xxxx')
  viewConfig;

  async render(fullpath, locals) {
    return myengine.render(fullpath, locals);
  }

  async renderString() { throw new Error('not implement'); }
};

These methods receive three arguments, renderString will pass tpl as the first argument instead of name in render.

render(name, locals, viewOptions)

  • name: the file path that can resolve from root (/view by default)
  • locals: data used by template
  • viewOptions: the view options for each render, it can override the view default config in config/config.default.js. Plugin should implement it if it has config.
    When you implement view engine, you will receive this options from render, the options contain:
    • root: it will resolve the name to full path, but seperating root and name in viewOptions.
    • name: the original name when call render
    • locals: the original locals when call render

renderString(tpl, locals, viewOptions)

  • tpl: the template string instead of the file, using in renderString
  • locals: same as render
  • viewOptions: same as render

Register

After define a view engine, you can register it.

typescript
// src/configuration.ts
import { Configuration, Inject, Provide } from '@midwayjs/core';
import * as koa from '@midwayjs/koa';
import * as view from '@midwayjs/view';
import { MyView } from './lib/my';

@Configuration({
  imports: [koa, view],
  importConfigs: [join(__dirname, 'config')]
})
export class AutoConfiguration {

  @Inject()
  viewManager: view.ViewManager;

  async onReady(){
    this.viewManager.use('ejs', MyView);
  }
}

You can define a view engine name, normally it's a template name.

Configuration

Root

Root is ${appDir}/view by default, but you can define multiple directory.

typescript
export default appInfo => {
  const appDir = appInfo.appDir;
  return {
    view: {
      rootDir: {
        default: `${appDir}/view`,
        anotherDir: `${appDir}/view2`
      }
    }
  }
}

defaultExtension

When render a file, you should specify a extension that let @midway/view know which engine you want to use. However you can define defaultExtension without write the extension.

typescript
// src/config/config.default.ts
export const view = {
  defaultExtension: '.html',
};

// controller
import { Inject, Provide } from '@midwayjs/core';
import { Context } from '@midwayjs/koa';

@Controller('/')
export class HomeController {

  @Inject()
  ctx: Context;

  @Get('/')
  async render(){
    // render user.html
    await this.ctx.render('user');
  }
}

viewEngine and defaultViewEngine

If you are using renderString, you should specify viewEngine in view config, see example above.

However, you can define defaultViewEngine without set each time.

js
// config/config.default.js
export const view = {
  defaultViewEngine: 'ejs',
};

License

MIT


File: packages/validate/README.md

midway validate module


this is a sub package for midway.

Document: https://midwayjs.org

License

MIT

2. Official Technical Reference & Guides (midwayjs/midwayjs.github.io)

File: README.md

midway site

bash
npm i
# dev site in docs
npm run dev
# run build
npm run deploy
git commit -m "docs:add site"
git push origin master

File: docs/en/index.md

English Document is not ready.

Please see docuemnt with ?translate=en parameter.

Like: introduction


File: docs/README.md


text
<nav>
      [使用文档](https://www.yuque.com/midwayjs/midway_v2)
      [示例库](http://demo.midwayjs.org/)
      [API](/api-reference/index.html)
      [Node 地下铁 Club](https://subway.midwayjs.org)
      [备用文档](start_app.html)
    </nav>
    
  




  
    一个面向未来的
    云端一体 Node.js 框架
    Midway 是一个适用于构建 Serverless 服务,传统应用、微服务,小程序后端的 Node.js 框架
  
  
    
      <a class="home-top-button button view" href="https://www.yuque.com/midwayjs/midway_v2">访问文档</a>
      
      
      
    
    <a class="home-top-button button white" href="https://github.com/midwayjs/midway">源码</a>
  




  Midway Serverless 2.0
  全新的一体化方案
  全新的 Serverless 测试方案
  业界首创的全栈开发方式
  我们的发布会已结束,可以扫描右侧二维码观看回放
  
    
      
      bilibili 前端圈(直播回放)
    
     
      
      Node.js 地下铁
    
  




  不论你在寻求何种解决方案,
  Midway 总能提供给你最适合的那一个
  
  
  
  <a class="home-solution-more button" href="http://demo.midwayjs.org/">查看所有解决方案</a>
  
    
      <a class="ad-middle-button button white" href="http://d2forum.alibaba-inc.com/" target="_blank">点击报名</a>
    
    
      <a class="ad-middle-button button white" href="https://mudu.tv/watch/7560584">了解更多</a>
    
  




  为什么选择 Midway?
  
    Serverless 应用云端一体
    Midway 不仅提供了和各个前端框架结合的能力,在传统的开发基础上,更增加了一体化研发模式,让前端业务能够更自如的调用 Node.js 代码,开发的更快更简单。
    
  
  
    代码复用和组件化能力
    Midway  不仅抽象出了满足不同场景的上层框架,也提供了跨场景复用的组件化能力,甚至还提供了业务代码的复用组件 ,让业务代码可以轻量化的拷贝和分享到不同的场景应用。
    
  
  
    一份代码,多场景部署
    Midway 提供了一套完整的解决方案,只需要写一次代码,就可以自动构建出适合于传统应用 ,微服务,乃至 Serverless 环境的代码包 ,方便用户移植程序到不同的部署环境。
    
  
  
    高并发业务稳定高效
    Midway 在 阿里集团内部已经普遍使用,经过了多次大促的洗礼,整个框架已经非常高效和稳定。默认情况下, Midway 在 Web Application 开发时提供了非常多的内置能力,用户无需再去查询其他能力。
    
  




  加入我们
  MidwayJs 是一个开源品牌,旗下的产品都为 MIT 协议,欢迎各位提交代码 ,一起共建 Node.js 生态。
  




  
    © 2021 ~ ∞ Midwayjs@Serverless
    <a class="link" href="https://github.com/midwayjs/midway">Github</a>
    <a class="link" href="https://github.com/midwayjs/midway/issues">Issue</a>
    <a class="link" href="https://www.yuque.com/midwayjs/topics">Help</a>
    <a class="link" href="http://demo.midwayjs.org/">Gallery</a>
  
  <a class="bottom-logo"></a>
  
    <a class="link" href="https://github.com/midwayjs/pandora">Pandora</a>
    <a class="link" href="https://github.com/midwayjs/injection">Injection</a>
    <a class="link" href="https://github.com/midwayjs/sandbox-docker">Sandbox</a>
    <a class="link" href="https://ice.work/">ICE</a>