在第1部分中,我讨论了在Nuxt中组织API服务器是多么容易。在第2部分中,我想告诉您从Nuxt fullstack服务器可以得到什么额外的好处。第2部分:加快服务器渲染速度!
让我们现在从示例codeandbox.io/s/codesandbox-nuxt-3gzhl示例中思考服务器的工作方式- 客户端请求主页3gzhl.sse.codesandbox.io
- Nuxt开始在服务器上渲染页面/pages/index.vue
- 来到
async fetch() {
this.users = await this.$api("users", "index");
},
- 通过爱可信,他使一个HTTP请求,在3gzhl.sse.codesandbox.io/api/users/index即 对我自己
- 建立连接,在服务器上创建一个新会话,并分配内存以处理http请求
- 通过http协议接受传入的请求,解析url,处理参数
- 执行服务器中间件
- Nuxt推出我们的API服务器
- JSON
- users.index(), JSON
- JSON http
- axios JSON
- API
现在假设我们在页面上有20个通过API请求数据的组件,因此在对Nuxt服务器的页面请求中,将建立20个附加的内部http连接,并且步骤 4-13将执行20次。Nuxt HTTP服务器每秒可以处理超过5.5万个请求,但是,创建内部HTTP请求后,我们将潜在的服务器资源减少了数十倍。但是,当我们在服务器上呈现页面时,我们可以直接访问/ api文件夹中的所有控制器/让我们更改逻辑,以便在服务器上呈现时,直接调用控制器代码,并在浏览器中调用时,请求是通过http发送的- 将文件/plugins/api-context.js重命名为/plugins/api-context.client.js
- 在设置/nuxt.config.js中更改文件名
plugins: ["~/plugins/api-context.client.js"]
现在,此$ .Api上下文仅可用于客户端代码
- 创建此$ 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;
}
});
};
- 连接服务器插件
/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- 为了消除外部连接速度的影响,我将接收数据替换为静态数据:
/api/users.js
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."
}
};
}
....
- 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;
}
});
};
- 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;
},
- 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";
...
- 现在比较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的唯一实例应承受中小型项目的负载