Na Parte 1, falei sobre como é fácil organizar um servidor de API no Nuxt . Na Parte 2, quero lhe dizer quais benefícios adicionais você pode obter do servidor Nuxt fullstack .Parte 2: acelerando a renderização do servidor!
Vamos pensar agora como nosso servidor funciona a partir do exemplo codesandbox.io/s/codesandbox-nuxt-3gzhl- O cliente solicita a página principal 3gzhl.sse.codesandbox.io
- O Nuxt começa a renderizar no servidor a página /pages/index.vue
- Chega a
async fetch() {
this.users = await this.$api("users", "index");
},
- Por axios, ele faz uma solicitação http em 3gzhl.sse.codesandbox.io/api/users/index, ou seja, em mim mesmo
- Uma conexão é estabelecida, uma nova sessão é criada no servidor e a memória é alocada para processar a solicitação http
- Uma solicitação de entrada é aceita via protocolo http , a URL é analisada, os parâmetros são processados
- Executa o middleware do servidor
- Nuxt lança nosso servidor de API
- JSON
- users.index(), JSON
- JSON http
- axios JSON
- API
Agora imagine que temos 20 componentes na página que solicitam dados por meio da API ; portanto, em uma solicitação para a página com o servidor Nuxt, 20 conexões http internas adicionais serão estabelecidas e as etapas 4-13 serão executadas 20 vezes. O servidor HTTP Nuxt pode processar mais de 55 mil solicitações por segundo; no entanto, ao criar solicitações HTTP internas, reduzimos os recursos potenciais do servidor em dezenas de vezes.Mas quando renderizamos a página no servidor, temos acesso direto a todos os controladores na pasta / api /Vamos mudar a lógica para que, ao renderizar no servidor, o código do controlador seja chamado diretamente e, quando chamado pelo navegador, a solicitação foi enviada via http- Renomeie o arquivo /plugins/api-context.js para /plugins/api-context.client.js
- altere o nome do arquivo nas configurações /nuxt.config.js
plugins: ["~/plugins/api-context.client.js"]
Agora, este contexto . $ Api está disponível apenas para o código do cliente
- crie esse contexto . $ api para chamar diretamente os controladores no servidor
/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;
}
});
};
- conecte o plugin do servidor
/nuxt.config.js
plugins: [
"~/plugins/api-context.client.js",
"~/plugins/api-context.server.js"
]
Agora, a função this. $ Api no servidor chama diretamente o método do controlador, e no cliente isso. $ Api envia uma solicitação http via axios .O código async fetch() {
this.users = await this.$api("users", "index");
},
ao renderizar no servidor, ele não executará uma solicitação http por si só, mas simplesmente conectará o arquivo /api/users.js através de require e chame o método index () , ou seja, itens de 4 a 13 não serão executados, mas apenas 10. Serão executados 10. No entanto, quando o cliente clicar no botão Atualizar no navegador , os mesmos dados serão solicitados via http . Aqui está o código completo: codesandbox.io/s/codesandbox-nuxt-pbriwTeste de performance
codesandbox.io/s/codesandbox-nuxt-rzdyw- Para eliminar a influência da velocidade das conexões externas, substituí o recebimento de dados por dados estáticos:
/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";
...
- Agora compare o tempo de execução do tempo de busca de renderização de chamada da API interna do servidor rzdyw.sse.codesandbox.io
: tempo de 1ms
de 0ms a um máximo de 2ms
Tempo de
busca de renderização de chamada da API http do servidor:
tempo de 71ms de 46ms a um máximo de 1059ms
e várias vezes o servidor geralmente travava com um erro
RangeError
Maximum call stack size exceeded
Aqui está um exemplo completo - codesandbox.io/s/codesandbox-nuxt-rzdywTotal Parte 2
- Com alterações mínimas, você pode acelerar a renderização do servidor em mais de 50 vezes. Em um exemplo ao vivo, a renderização da minha página foi acelerada em ~ 1,7 vezes
- Recursos do servidor HTTP do nó reduzidos significativamente
- De maneira otimizada, a única instância do Nuxt deve suportar a carga de projetos pequenos e médios