In Teil 1 habe ich darüber gesprochen, wie einfach es ist, einen API-Server in Nuxt zu organisieren . In Teil 2 möchte ich Ihnen erklären, welche zusätzlichen Vorteile Sie vom Nuxt-Fullstack-Server erhalten können .Teil 2: Beschleunigung des Server-Renderings!
Lassen Sie uns nun anhand des Beispiels Codesandbox.io/s/codesandbox-nuxt-3gzhl überlegen, wie unser Server funktioniert- Der Client fordert die Hauptseite 3gzhl.sse.codesandbox.io an
- Nuxt beginnt auf dem Server mit dem Rendern der Seite /pages/index.vue
- Kommt zu
async fetch() {
this.users = await this.$api("users", "index");
},
- Über axios stellt er eine http-Anfrage unter 3gzhl.sse.codesandbox.io/api/users/index, d.h. auf mich
- Eine Verbindung wird hergestellt, eine neue Sitzung auf dem Server erstellt und Speicher für die Verarbeitung der http-Anforderung zugewiesen
- Eine eingehende Anfrage wird über das http- Protokoll akzeptiert , die URL wird analysiert, die Parameter werden verarbeitet
- Führt Server-Middleware aus
- Nuxt startet unseren API-Server
- JSON
- users.index(), JSON
- JSON http
- axios JSON
- API
Stellen Sie sich nun vor, wir haben 20 Komponenten auf der Seite, die Daten über die API anfordern. In einer Anforderung für die Seite mit dem Nuxt- Server werden 20 zusätzliche interne http- Verbindungen hergestellt und die Schritte 4 bis 13 werden 20 Mal ausgeführt. Der Nuxt-HTTP-Server kann mehr als 55.000 Anforderungen pro Sekunde verarbeiten. Wenn Sie jedoch interne HTTP-Anforderungen erstellen, reduzieren wir die potenziellen Serverressourcen um das Zehnfache.Wenn wir die Seite auf dem Server rendern, haben wir direkten Zugriff auf alle Controller im Ordner / api /Ändern wir die Logik so, dass beim Rendern auf dem Server der Controller-Code direkt aufgerufen wird und beim Aufruf vom Browser die Anforderung über http gesendet wurde- Benennen Sie die Datei /plugins/api-context.js in /plugins/api-context.client.js um
- Ändern Sie den Dateinamen in den Einstellungen /nuxt.config.js
plugins: ["~/plugins/api-context.client.js"]
Jetzt ist dieser. $ Api- Kontext nur für Client-Code verfügbar
- Erstellen Sie diesen. $ api- Kontext , um die Controller direkt auf dem Server
/plugins/api-context.server.js aufzurufen
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;
}
});
};
- Verbinden Sie das Server-Plugin
/nuxt.config.js
plugins: [
"~/plugins/api-context.client.js",
"~/plugins/api-context.server.js"
]
Jetzt ruft die Funktion this. $ Api auf dem Server die Controller-Methode direkt auf, und auf dem Client dies. $ Api sendet eine http-Anfrage über axios .Der Code async fetch() {
this.users = await this.$api("users", "index");
},
Beim Rendern auf dem Server wird keine http-Anforderung für sich selbst ausgeführt, sondern einfach die Datei /api/users.js über require verbunden und die index () -Methode aufgerufen , d. h. Elemente von 4 bis 13 werden nicht ausgeführt, aber nur 10 werden ausgeführt. Wenn der Client jedoch im Browser auf die Schaltfläche Aktualisieren klickt , werden dieselben Daten über http angefordert . Hier ist der vollständige Code: Codesandbox.io/s/codesandbox-nuxt-pbriwLeistungstest
Codesandbox.io/s/codesandbox-nuxt-rzdyw- Um den Einfluss der Geschwindigkeit externer Verbindungen zu beseitigen, habe ich den Empfang von Daten durch statische Daten ersetzt:
/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";
...
- Vergleichen Sie nun die Ausführungszeit von rzdyw.sse.codesandbox.io
Server internen API - Aufruf Rendering Abrufzeit: 1 ms
Zeit von 0 ms bis maximal 2 ms
rzdyw.sse.codesandbox.io/httpcall
Server http - API - Aufruf Rendering holt Zeit: 71MS
Zeit von 46ms bis maximal 1059ms
und mehrmals stürzte der Server im Allgemeinen mit einem Fehler ab
RangeError
Maximum call stack size exceeded
Hier ist ein vollständiges Beispiel - Codesandbox.io/s/codesandbox-nuxt-rzdywGesamtteil 2
- Mit minimalen Änderungen können Sie das Rendern von Servern um mehr als das 50-fache beschleunigen. In einem Live-Beispiel wurde das Rendern meiner Seite um das ~ 1,7-fache beschleunigt
- Die HTTP-Serverressourcen des Knotens wurden erheblich reduziert
- In optimierter Weise sollte die einzige Instanz von Nuxt der Last kleiner und mittlerer Projekte standhalten