Nuxt全栈服务器的附加SSR性能(第2部分)

Nuxt全栈服务器具有额外的SSR性能


在第1部分中,我讨论了Nuxt中组织API服务器是多么容易在第2部分中,我想告诉您从Nuxt fullstack服务器可以得到什么额外的好处

第2部分:加快服务器渲染速度!


让我们现在从示例codeandbox.io/s/codesandbox-nuxt-3gzhl示例中思考服务器的工作方式

  1. 客户端请求主页3gzhl.sse.codesandbox.io
  2. Nuxt开始在服务器上渲染页面/pages/index.vue
  3. 来到

      async fetch() {
        this.users = await this.$api("users", "index");
      },
    
  4. 通过爱可信,他使一个HTTP请求,在3gzhl.sse.codesandbox.io/api/users/index对我自己
  5. 建立连接,在服务器上创建一个新会话,并分配内存以处理http请求
  6. 通过http协议接受传入的请求,解析url,处理参数
  7. 执行服务器中间件
  8. Nuxt推出我们的API服务器
  9. JSON
  10. users.index(), JSON
  11. JSON http
  12. axios JSON
  13. API

现在假设我们在页面上有20个通过API请求数据的组件,因此在对Nuxt服务器的页面请求中,将建立20个附加的内部http连接,并且步骤 4-13将执行20次。Nuxt HTTP服务器每秒可以处理超过5.5万个请求,但是,创建内部HTTP请求后,我们将潜在的服务器资源减少了数十倍。

但是,当我们在服务器上呈现页面时,我们可以直接访问/ api文件夹中的所有控制器/

让我们更改逻辑,以便在服务器上呈现时,直接调用控制器代码,并在浏览器中调用时,请求是通过http发送的

  1. 将文件/plugins/api-context.js重命名/plugins/api-context.client.js
  2. 在设置/nuxt.config.js中更改文件名

      plugins: ["~/plugins/api-context.client.js"]
    

    现在,此$ .Api上下文仅可用于客户端代码
  3. 创建此$ api上下文以直接调用

    /plugins/api-context.server.js 服务器上的控制器
    export default (context, inject) => {
      inject("api", async (controller, method, params) => {
        try {
          let api = require("../api/" + controller.replace(/^\/+|\/+$|\.+/g, ""));
          return await api[method](params);
        } catch (e) {
          console.error(e);
          throw e;
        }
      });
    };
    
  4. 连接服务器插件

    /nuxt.config.js
      plugins: [
        "~/plugins/api-context.client.js",
        "~/plugins/api-context.server.js"
      ]
    

现在服务器上的函数this。$ Api将直接调用controller方法,而在客户端上,此。$ Api通过axios发送一个http请求 编码



  async fetch() {
    this.users = await this.$api("users", "index");
  },

在服务器上进行渲染时,它不会对其自身执行http请求,而只是通过require连接/api/users.js文件并调用index()方法,即 4-13中的项目将不会执行,只有10个项目会被执行,

但是,当客户端单击浏览器中的Refresh按钮时,将通过http请求相同的数据

这是完整的代码:codesandbox.io/s/codesandbox-nuxt-pbriw

性能测试


codeandbox.io/s/codesandbox-nuxt-rzdyw

  1. 为了消除外部连接速度的影响,我将接收数据替换为静态数据:

    /api/users.js
    // we can get data from any DB
    async function getDataFromDB() {
      return {
        page: 1,
        per_page: 6,
        total: 12,
        total_pages: 2,
        data: [
          {
            id: 1,
            email: "george.bluth@reqres.in",
            first_name: "George",
            last_name: "Bluth",
            avatar:
              "https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"
          },
          {
            id: 2,
            email: "janet.weaver@reqres.in",
            first_name: "Janet",
            last_name: "Weaver",
            avatar:
              "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
          },
          {
            id: 3,
            email: "emma.wong@reqres.in",
            first_name: "Emma",
            last_name: "Wong",
            avatar:
              "https://s3.amazonaws.com/uifaces/faces/twitter/olegpogodaev/128.jpg"
          },
          {
            id: 4,
            email: "eve.holt@reqres.in",
            first_name: "Eve",
            last_name: "Holt",
            avatar:
              "https://s3.amazonaws.com/uifaces/faces/twitter/marcoramires/128.jpg"
          },
          {
            id: 5,
            email: "charles.morris@reqres.in",
            first_name: "Charles",
            last_name: "Morris",
            avatar:
              "https://s3.amazonaws.com/uifaces/faces/twitter/stephenmoon/128.jpg"
          },
          {
            id: 6,
            email: "tracey.ramos@reqres.in",
            first_name: "Tracey",
            last_name: "Ramos",
            avatar:
              "https://s3.amazonaws.com/uifaces/faces/twitter/bigmancho/128.jpg"
          }
        ],
        ad: {
          company: "StatusCode Weekly",
          url: "http://statuscode.org/",
          text:
            "A weekly newsletter focusing on software development, infrastructure, the server, performance, and the stack end of things."
        }
      };
      /*
      return (await require("axios").get(`https://reqres.in/api/users?page=1`))
        .data;
      */
    }
    ....
    
  2. api , http

    /plugins/api-context.server.js
    export default (context, inject) => {
      inject("server", () => true);
      inject("api", async (controller, method, params) => {
        try {
          if (params && params.httpcall) {
            return await context.$axios["$" + (params ? "post" : "get")](
              "/api/" + controller + "/" + method,
              params
            );
          }
          let api = require("../api/" + controller.replace(/^\/+|\/+$|\.+/g, ""));
          return await api[method](params);
        } catch (e) {
          console.error(e);
          throw e;
        }
      });
    };
    
  3. index.vue fetch api 50

    /pages/index.vue
      async fetch() {
        let start = new Date();
        let promises = [];
        let callNum = 50;
        for (let i = 0; i < callNum; i++) {
          promises.push(this.$api("users", "index"));
        }
    
        let arr = await Promise.all(
          promises.map(async p => {
            return await p;
          })
        );
    
        let res = [];
        for (let r of arr) {
          res = res.concat(r);
        }
    
        this.users = res;
        this.fetchType =
          (this.$server && this.$server() ? "Server internal" : "Client http") +
          " API call";
        this.fetchTime = new Date() - start;
      },
    
  4. httpcall.vue fetch api 50 http

    /pages/httpcall.vue
    ...
          promises.push(this.$api("users", "index", { httpcall: true }));
    ...
        this.fetchType =
          (this.$server && this.$server() ? "Server http" : "Client http") +
          " API call";
    ...
    
  5. 现在比较rzdyw.sse.codesandbox.io

    服务器内部API调用呈现时间的执行时间:1ms
    时间(从0ms到最大2ms)

    rzdyw.sse.codesandbox.io/httpcall
    服务器http API调用呈现时间:71ms
    时间(从46ms到最大1059ms)
    并且几次服务器通常因错误而崩溃

    RangeError
    Maximum call stack size exceeded

这是一个完整的示例-codesandbox.io/s/codesandbox-nuxt-rzdyw

总计第2部分


  • 通过最小的更改,您可以将服务器渲染速度提高50倍以上,在一个实时示例中,我的页面渲染速度提高了约1.7倍
  • 节点HTTP服务器资源大大减少
  • 以优化的方式,Nuxt的唯一实例应承受中小型项目的负载

All Articles